From 24af0f5a2292dd9004235dfc9a14130394b9537c Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 21 May 2021 10:50:36 -0700 Subject: [PATCH 1/3] Add a basic example with HTTP headers --- valuable/examples/http_headers.rs | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 valuable/examples/http_headers.rs diff --git a/valuable/examples/http_headers.rs b/valuable/examples/http_headers.rs new file mode 100644 index 0000000..c3da253 --- /dev/null +++ b/valuable/examples/http_headers.rs @@ -0,0 +1,68 @@ +use valuable::*; + +#[derive(Valuable)] +struct Headers { + user_agent: String, + host: String, + content_type: ContentType, + accept_encoding: Vec, +} + +#[derive(Valuable)] +struct ContentType { + mime: String, + charset: String, +} + +// Visit the root of the Headers struct +struct VisitHeaders(Vec); + +// Visit the accept_encoding field. +struct VisitAcceptEncoding<'a>(&'a mut Vec); + +impl Visit for VisitHeaders { + fn visit_value(&mut self, value: Value<'_>) { + // We expect a `Structable` representing the `Headers` struct. + match value { + // Visiting the struct will call `visit_named_fields`. + Value::Structable(v) => v.visit(self), + // Ignore other patterns + _ => {} + } + } + + fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { + // We only care about `accept_encoding` + if let Some(Value::Listable(accept_encoding)) = named_values.get_by_name("accept_encoding") + { + let mut visit = VisitAcceptEncoding(&mut self.0); + accept_encoding.visit(&mut visit); + } + } +} + +impl Visit for VisitAcceptEncoding<'_> { + fn visit_value(&mut self, value: Value<'_>) { + if let Some(accept_encoding) = value.as_str() { + self.0.push(accept_encoding.to_string()) + } + } +} + +fn main() { + let headers = Headers { + user_agent: "Mozilla/4.0 (compatible; MSIE5.01; Windows NT)".to_string(), + host: "www.example.com".to_string(), + content_type: ContentType { + mime: "text/xml".to_string(), + charset: "utf-8".to_string(), + }, + accept_encoding: vec!["gzip".to_string(), "deflate".to_string()], + }; + + // Extract the "accept-encoding" headers + let mut visit = VisitHeaders(vec![]); + valuable::visit(&headers, &mut visit); + + assert_eq!(&["gzip", "deflate"], &visit.0[..]); +} From 7571b30bc51d79a7b9a4f85684201006c39373da Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 21 May 2021 11:14:55 -0700 Subject: [PATCH 2/3] tweak --- valuable/examples/http_headers.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/valuable/examples/http_headers.rs b/valuable/examples/http_headers.rs index c3da253..ac02a14 100644 --- a/valuable/examples/http_headers.rs +++ b/valuable/examples/http_headers.rs @@ -33,10 +33,12 @@ impl Visit for VisitHeaders { fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) { // We only care about `accept_encoding` - if let Some(Value::Listable(accept_encoding)) = named_values.get_by_name("accept_encoding") - { - let mut visit = VisitAcceptEncoding(&mut self.0); - accept_encoding.visit(&mut visit); + match named_values.get_by_name("accept_encoding") { + Some(Value::Listable(accept_encoding)) => { + let mut visit = VisitAcceptEncoding(&mut self.0); + accept_encoding.visit(&mut visit); + } + _ => {} } } } From ee1f1db47eeb5438b83cf8cf05718896d2e0fc33 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 24 May 2021 11:00:04 -0700 Subject: [PATCH 3/3] tweak example --- valuable/examples/http_headers.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/valuable/examples/http_headers.rs b/valuable/examples/http_headers.rs index ac02a14..37c9bc3 100644 --- a/valuable/examples/http_headers.rs +++ b/valuable/examples/http_headers.rs @@ -14,11 +14,19 @@ struct ContentType { charset: String, } -// Visit the root of the Headers struct -struct VisitHeaders(Vec); +// Visit the root of the Headers struct. This visitor will find the +// `accept_encoding` field on `Headers` and extract the contents. All other fields +// are ignored. +struct VisitHeaders { + /// The extracted `accept-encoding` header values. + accept_encoding: Vec, +} -// Visit the accept_encoding field. -struct VisitAcceptEncoding<'a>(&'a mut Vec); +// Visit the `accept-encoding` `Vec`. This visitor iterates the items in the +// list and pushes it into its `accept_encoding` vector. +struct VisitAcceptEncoding<'a> { + accept_encoding: &'a mut Vec, +} impl Visit for VisitHeaders { fn visit_value(&mut self, value: Value<'_>) { @@ -35,7 +43,11 @@ impl Visit for VisitHeaders { // We only care about `accept_encoding` match named_values.get_by_name("accept_encoding") { Some(Value::Listable(accept_encoding)) => { - let mut visit = VisitAcceptEncoding(&mut self.0); + // Create the `VisitAcceptEncoding` instance to visit the items + // in `Listable`. + let mut visit = VisitAcceptEncoding { + accept_encoding: &mut self.accept_encoding, + }; accept_encoding.visit(&mut visit); } _ => {} @@ -44,9 +56,10 @@ impl Visit for VisitHeaders { } impl Visit for VisitAcceptEncoding<'_> { + /// Method called when visiting a `Listable`. fn visit_value(&mut self, value: Value<'_>) { if let Some(accept_encoding) = value.as_str() { - self.0.push(accept_encoding.to_string()) + self.accept_encoding.push(accept_encoding.to_string()) } } } @@ -63,8 +76,8 @@ fn main() { }; // Extract the "accept-encoding" headers - let mut visit = VisitHeaders(vec![]); + let mut visit = VisitHeaders { accept_encoding: vec![] }; valuable::visit(&headers, &mut visit); - assert_eq!(&["gzip", "deflate"], &visit.0[..]); + assert_eq!(&["gzip", "deflate"], &visit.accept_encoding[..]); }