Julio Biason
1 year ago
4 changed files with 1187 additions and 0 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "internetiterator" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
reqwest = { version = "0.11.18", features = ["blocking", "json"] } |
||||||
|
serde = { version = "1.0.171", features = ["derive"] } |
@ -0,0 +1,3 @@ |
|||||||
|
# InternetIterator |
||||||
|
|
||||||
|
Iterator over data from the internet |
@ -0,0 +1,99 @@ |
|||||||
|
use std::slice::Iter; |
||||||
|
|
||||||
|
use reqwest::blocking::Client; |
||||||
|
use serde::{de::DeserializeOwned, Deserialize}; |
||||||
|
|
||||||
|
static LIB_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); |
||||||
|
|
||||||
|
/// This is the connection handler.
|
||||||
|
/// API documentation is here:
|
||||||
|
/// https://punkapi.com/documentation/v2
|
||||||
|
struct Punk { |
||||||
|
url: String, |
||||||
|
client: Client, |
||||||
|
} |
||||||
|
|
||||||
|
impl Punk { |
||||||
|
pub fn new(/* connection information here */) -> Self { |
||||||
|
Self { |
||||||
|
url: "https://api.punkapi.com/v2/".into(), |
||||||
|
client: Client::builder() |
||||||
|
.user_agent(LIB_USER_AGENT) |
||||||
|
.build() |
||||||
|
.unwrap(), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Information about beers.
|
||||||
|
/// (This is done like this 'cause we want a function call/method/attribute for each different
|
||||||
|
/// information in the server; it is just that this specific server have only one data type).
|
||||||
|
pub fn beers(&self) -> Result<BeerIter, reqwest::Error> { |
||||||
|
BeerIter::new(self) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get<T: DeserializeOwned>(&self, page: u16) -> Result<T, reqwest::Error> { |
||||||
|
Ok(self.client.get(&self.url).send()?.json::<T>()?) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// This is a definition of data from the API
|
||||||
|
#[derive(Deserialize)] |
||||||
|
struct Beer { |
||||||
|
id: u16, |
||||||
|
name: String, |
||||||
|
tagline: String, |
||||||
|
// ... and let's ignore everything else 'cause that's enough.
|
||||||
|
} |
||||||
|
|
||||||
|
/// This is the magical iterator that gets stuff from the internet
|
||||||
|
struct BeerIter<'a> { |
||||||
|
connection: &'a Punk, |
||||||
|
data: Vec<Beer>, |
||||||
|
iter: Option<Iter<'a, Beer>>, |
||||||
|
page: u16, |
||||||
|
} |
||||||
|
|
||||||
|
impl<'a> BeerIter<'a> { |
||||||
|
pub fn new(connection: &'a Punk) -> Result<Self, reqwest::Error> { |
||||||
|
let mut result = Self { |
||||||
|
connection, |
||||||
|
data: Vec::new(), |
||||||
|
iter: None, |
||||||
|
page: 1 |
||||||
|
}; |
||||||
|
result.next_page()?; |
||||||
|
Ok(result) |
||||||
|
} |
||||||
|
|
||||||
|
fn next_page(&mut self) -> Result<(), reqwest::Error> { |
||||||
|
let page = self.connection.get::<Vec<Beer>>(self.page)?; |
||||||
|
self.data = page; |
||||||
|
self.iter = Some(self.data.iter()); |
||||||
|
self.page += 1; |
||||||
|
Ok(()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl<'a> Iterator for BeerIter<'a> { |
||||||
|
type Item = &'a Beer; |
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> { |
||||||
|
if let Some(record) = self.iter?.next() { |
||||||
|
Some(record) |
||||||
|
} else { |
||||||
|
self.next_page(); |
||||||
|
Some(self.iter?.next().unwrap()) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let connection = Punk::new(); |
||||||
|
let beers = connection.beers().expect("Failed to get the initial data"); |
||||||
|
// for beer in beers {
|
||||||
|
// println!(" ID: {}", beer.id);
|
||||||
|
// println!(" Name: {}", beer.name);
|
||||||
|
// println!("Tagline: {}\n", beer.tagline);
|
||||||
|
// }
|
||||||
|
println!("Hello, world!"); |
||||||
|
} |
Loading…
Reference in new issue