Why can "rust cookie::CookieJar" get a value through str type - cookies

I know that the underlying data structure is a HashSet, but why can the get method use the &str type instead of the cookie structure?
cargo.toml
[dependencies]
cookie = "0.14"
src/main.rs
use cookie::{Cookie, CookieJar};
fn main() {
let mut jar = CookieJar::new();
jar.add(Cookie::new("a", "one"));
jar.add(Cookie::new("b", "two"));
assert_eq!(jar.get("a").map(|c| c.value()), Some("one"));
assert_eq!(jar.get("b").map(|c| c.value()), Some("two"));
jar.remove(Cookie::named("b"));
assert!(jar.get("b").is_none());
}

The authors of cookie-rs implemented the Hash and Borrow trait for the values of the HashSet.
Here's an example mimicking the same behavior:
use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::collections::HashSet;
#[derive(Debug, Eq)]
struct Cookie<'a> {
name: &'a str,
id: u64,
}
impl Hash for Cookie<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl PartialEq for Cookie<'_> {
fn eq(&self, other: &Cookie) -> bool {
self.name == other.name
}
}
impl Borrow<str> for Cookie<'_> {
fn borrow(&self) -> &str {
self.name
}
}
fn main() {
let mut cookies: HashSet<Cookie> = HashSet::new();
cookies.insert(Cookie {
name: "example",
id: 42,
});
println!("{:?}", cookies.get("example"));
}
That would give us:
Some(Cookie { name: "example", id: 42 })

Related

Append to Node to an Empty LinkedList in Rust, self.head.borrow_next() is None and not self.tail

I have tried to reimplement LinkedList in Rust, below are my codes:
#![allow(dead_code)]
use std::cell::{RefCell, Ref, RefMut};
use std::rc::Rc;
type WrappedNode<T> = Rc<RefCell<Node<T>>>;
#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct Node<T> where
T: Clone
{
next: Option<WrappedNode<T>>,
data: T,
}
#[derive(Debug, PartialOrd, PartialEq)]
pub struct LinkedList<T> where
T: Clone
{
head: Option<WrappedNode<T>>,
tail: Option<WrappedNode<T>>,
}
impl<T> Iterator for LinkedList<T> where
T: Clone
{
type Item = WrappedNode<T>;
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
impl<T> Node<T> where
T: Clone
{
pub fn new(data: T) -> Self {
Self {
next: None,
data,
}
}
pub fn borrow_data(self: &Self) -> &T {
&self.data
}
pub fn borrow_next(self: &Self) -> Option<Ref<Node<T>>> {
match &self.next {
Some(next_exists) => {
Some(next_exists.borrow())
},
None => {
None
}
}
}
pub fn borrow_mut_next(self: &Self) -> Option<RefMut<Node<T>>> {
match &self.next {
Some(next_exists) => {
Some(next_exists.borrow_mut())
},
None => {
None
}
}
}
pub fn set_next(self: &mut Self, next: Node<T>) {
let next_node = Rc::new(RefCell::new(next));
self.next = Some(next_node);
}
}
impl<T> LinkedList<T> where
T: Clone
{
pub fn new_empty() -> Self {
Self {
head: None,
tail: None,
}
}
pub fn new_with_node(first_node: Node<T>) -> Self {
let mut new_ll = Self::new_empty();
Self::append(&mut new_ll, first_node);
new_ll
}
pub fn append(&mut self, node: Node<T>) {
assert!(node.next.is_none()); // make sure its not joining two linkedlists
match self.tail.take() {
Some(old_tail) => {
old_tail
.borrow_mut()
.set_next(node.clone());
},
None => {
let mut node_clone = node.clone();
node_clone.next = self.tail.clone();
self.head = Some(Rc::new(RefCell::new(node_clone)));
}
}
self.tail = Some(Rc::new(RefCell::new(node)));
}
}
// CRUD -> create new, add to head tail, read head tail, update anywhere, delete anywhere, delete head tail
#[cfg(test)]
mod tests {
use super:: {Node, LinkedList};
use std::rc::Rc;
use std::cell::RefCell;
#[test]
fn test_node_ref_data() {
let node = Node::new(5);
assert_eq!(node.borrow_data(), &5);
}
#[test]
fn test_node_ref_next() {
let node = Node::new(5);
assert!(node.borrow_next().is_none());
}
#[test]
fn test_node_set_next() {
let mut node = Node::new(33);
let next_node = Node::new(34);
Node::set_next(&mut node,
next_node);
assert_eq!(node
.borrow_next()
.unwrap()
.borrow_data(), &34);
}
#[test]
fn test_ll_new_empty() {
#[derive(Debug, PartialEq, PartialOrd, Clone)]
struct NTH;
let new_ll = LinkedList::<NTH>::new_empty();
assert_eq!(new_ll, LinkedList{head: None, tail: None})
}
#[test]
fn test_ll_new_with_node() {
let new_node = Node::new(45);
let new_node_two = new_node.clone();
let new_node_three = new_node.clone();
let new_ll = LinkedList::new_with_node(new_node);
let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
let new_node_three = Some(Rc::new(RefCell::new(new_node_three)));
assert_eq!(new_ll, LinkedList{head: new_node_two, tail: new_node_three})
}
#[test]
fn test_ll_new_with_node_head_borrow_next_is_tail() {
let new_node = Node::new(45);
let new_node_two = new_node.clone();
let new_ll = LinkedList::new_with_node(new_node);
let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
assert_eq!(new_ll
.head
.unwrap()
.borrow()
.borrow_next()
.unwrap()
.borrow_data(), new_node_two.unwrap().borrow().borrow_data());
}
#[test]
fn test_ll_append_tail() {
let new_node = Node::new(45);
let new_node_two = new_node.clone();
let mut new_ll = LinkedList::new_with_node(new_node);
let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
let append_node = Node::new(77);
LinkedList::append(&mut new_ll, append_node);
assert_eq!(new_ll
.tail
.unwrap()
.borrow()
.borrow_data(), &77)
}
#[test]
fn test_ll_append_first_borrow_next() {
let new_node = Node::new(45);
let new_node_two = new_node.clone();
let mut new_ll = LinkedList::new_with_node(new_node);
let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
let append_node = Node::new(77);
LinkedList::append(&mut new_ll, append_node);
assert_eq!(new_ll
.head
.unwrap()
.borrow()
.borrow_next()
.unwrap()
.borrow_data(), &77)
}
// end of tests
}
Two tests failed, as shown below:
running 8 tests
test same_type_linked_list::tests::test_ll_new_empty ... ok
test same_type_linked_list::tests::test_ll_append_tail ... ok
test same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail ... FAILED
test same_type_linked_list::tests::test_ll_append_first_borrow_next ... FAILED
test same_type_linked_list::tests::test_ll_new_with_node ... ok
test same_type_linked_list::tests::test_node_ref_data ... ok
test same_type_linked_list::tests::test_node_set_next ... ok
test same_type_linked_list::tests::test_node_ref_next ... ok
failures:
---- same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail stdout ----
thread 'same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail' panicked at 'called `Option::unwrap()` on a `None` value', src/same_type_linked_list.rs:176:14
---- same_type_linked_list::tests::test_ll_append_first_borrow_next stdout ----
thread 'same_type_linked_list::tests::test_ll_append_first_borrow_next' panicked at 'called `Option::unwrap()` on a `None` value', src/same_type_linked_list.rs:210:16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
same_type_linked_list::tests::test_ll_append_first_borrow_next
same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail
I suspect during the appending of a new Node<T>, concretely Node<u64>, to an empty LinkedList the self.head.next is not pointing to self.tail, despite me setting it explicitly. The error occurs when I call unwrap() on the None value which is returned from borrow_next(), an associated method of Node<T> to return a reference of the field .next. That means that new_ll.head.borrow_next() which ideally should return a reference to new_ll.tail instead returns a None, meaning that it is not pointing to new_ll.tail when a first node is appended/inserted into a completely empty LinkedList.
Looking at your code the head node is the one that you give to in
LinkedList::new_with_node()
Its calling
pub fn new_empty() -> Self {
Self {
head: None,
tail: None,
}
i.e. its initialized with no head node. So when you construct your list with a node you are adding a head
pub fn new_with_node(first_node: Node<T>) -> Self {
let mut new_ll = Self::new_empty();
Self::append(&mut new_ll, first_node);
new_ll
}
pub fn append(&mut self, node: Node<T>) {
assert!(node.next.is_none()); // make sure its not joining two linkedlists
match self.tail.take() {
Some(old_tail) => {
old_tail
.borrow_mut()
.set_next(node.clone());
},
None => {
let mut node_clone = node.clone();
node_clone.next = self.tail.clone();
self.head = Some(Rc::new(RefCell::new(node_clone)));
}
}
You are also calling append by explicitly passing the newly created list as self.
Self::append(&mut new_ll, first_node);
You could have called it
new_ll.append(first_node)
You are assuming there is another node beyond the head in your test:
assert_eq!(new_ll
.head
.unwrap()
.borrow()
.borrow_next()
.unwrap()
.borrow_data(), &77)

How to assert two variables are equal when the implementation of PartialEq isn't appropriate?

In my program, I represent "events" with the following structure:
struct Event {
value: &'static str,
timestamp: usize,
}
So far, I used PartialEq to compare Event variables: most of the time, I consider two Events to be equal if their value is the same:
impl PartialEq for Event {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_loose_equality() {
let a = Event { value: "a-value", timestamp: 12345 };
let b = Event { value: "a-value", timestamp: 23456 };
assert_eq!(a, b);
}
}
However, in certain tests, I would like to ensure that two such variables are "strictly equals": The test should fail they have different timestamp (are not the same in respect to Eq).
As per the documentation of assert_eq!:
Asserts that two expressions are equal to each other (using PartialEq).
source
So, I am looking for an Eq equivalent, an assert_Eq_eq! in sort.
(or am I misunderstanding how Eq works and should be used?)
Here is what I fail to complete:
impl Eq for Event {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_strict_equality() {
let a = Event { value: "a-value", timestamp: 12345 };
let b = Event { value: "a-value", timestamp: 12345 };
// ???
}
}
You're swimming upstream fighting against the current. Go with the flow. Let PartialEq be strict equality and define a separate trait or method for loose equality.
#[derive(Eq, PartialEq)]
struct Event { .. }
impl Event {
fn loose_eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[test]
fn test_loose_equality() {
let a = Event { value: "a-value", timestamp: 12345 };
let b = Event { value: "a-value", timestamp: 23456 };
assert!(a.loose_eq(b));
}
I would create "views" of the type as appropriate:
struct Event {
value: &'static str,
timestamp: usize,
}
#[derive(Debug, PartialEq)]
struct Exact<'a> {
value: &'a &'static str,
timestamp: &'a usize,
}
impl Event {
fn exact(&self) -> Exact<'_> {
let Self { value, timestamp } = self;
Exact { value, timestamp }
}
}
fn demo(a: Event, b: Event) {
assert_eq!(a.exact(), b.exact());
}
Here I've chosen to take references to each of the fields to demonstrate the general case, but you don't need references for this specific example (&str and usize implement Copy and are small).
You could also choose to not implement PartialEq on the original type at all, and only perform comparisons through views:
assert_eq!(a.exact(), b.exact());
assert_eq!(a.loose(), b.loose());
If you need the strict equality only in tests, and your struct only has two fields, I'd simply compare these fields directly:
let a = Event { value: "a-value", timestamp: 12345 };
let b = Event { value: "a-value", timestamp: 12345 };
assert_eq!(a.value, b.value);
assert_eq!(a.timestamp, b.timestamp);
This looks like the easiest and most readable option to me.
Yes, you are misunderstanding something. Eq doesn't have any new methods over PartialEq. It's just an assertion that the implementation of PartialEq is reflexive (as well as the transitivity and symmetry assumed with PartialEq).
If you want to have a different "strict" equality, you could make your own trait (if you expect to use this a lot) or simply have a method fn strict_eq(&self, other: &Self) -> bool attached to Event.
Given such a method you could write a macro to use that method.
The full source for assert_eq! can be found here and could be easily adapted, but a (perhaps overly) simple version would be something like
macro_rules! assert_strict_eq {
($left: expr, $right: expr) => {
if !$left.strict_eq(&$right) {
panic!(r#"assertion failed: `(left == right)`
left: `{:?}`,
right: `{:?}`"#, $left, $right)
}
}
}
(example usage)
Unlike JavaScript, Rust does not support equal vs. strict equal.
However, you can achieve similar effect by implementing your own trait and macro:
pub trait StrictEq {
fn strict_eq(&self, other: &Self) -> bool;
}
macro_rules! assert_strict_eq {
($left:expr, $right:expr) => {{
match (&$left, &$right) {
(left_val, right_val) => {
assert!(left_val.strict_eq(right_val));
}
}
}};
}
The implementation for Event would be rather simple:
impl StrictEq for Event {
fn strict_eq(&self, other: &Self) -> bool {
self.value == other.value && self.timestamp == other.timestamp
}
}

Mock instance inside serde implementation

I'm trying to implement custom deserialization function/method which uses some external functionality. The function creates an instance and uses its methods. It's working fine, but I can't figure out how to mock the service in tests.
More general question is: how to provide a state to deserialization function/method?
The code below illustrates what I mean.
MagickBook is an external service which holds a state and contains some essential logic in MagickBook::find method.
Scroll is a deserializable data structure, which should be deserialized using the logic from MagicBook.
I'd like to have a way to provide particular instance of MagicBook from the outside, at the moment of deserialization. For example in tests.
Rust Playground
use serde::de::{Deserialize, Deserializer}; // 1.0.82
use serde_derive::Deserialize; // 1.0.82
use serde_json; // 1.0.33
struct MagickBook;
// Some service which I want to mock in the test
impl MagickBook {
fn new() -> Self {
Self {}
}
fn find(&self, _kind: &str) -> isize {
let effect = 42;
// Here we do some logic depending on input parameter
// -- snip --
return effect;
}
}
#[derive(Deserialize, PartialEq, Debug)]
struct Scroll {
#[serde(rename = "kind")]
#[serde(deserialize_with = "deserialize_effect")]
effect: isize,
}
fn deserialize_effect<'de, D>(deserializer: D) -> Result<isize, D::Error>
where
D: Deserializer<'de>,
{
let book = MagickBook::new();
Ok(book.find(&String::deserialize(deserializer)?))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn main() {
let scroll: Scroll = serde_json::from_str("{\"kind\":\"wind\"}").unwrap();
assert_eq!(scroll, Scroll { effect: 42 });
}
}
I would recommend accessing the mock through an internally mutable thread-local instance.
use serde::{Deserialize, Deserializer};
use std::cell::RefCell;
struct MagickBook {
value: isize,
}
thread_local! {
static MAGICK_BOOK: RefCell<MagickBook> = RefCell::new(MagickBook::new());
}
impl MagickBook {
fn new() -> Self {
MagickBook { value: 0 }
}
fn find(&self, _kind: &str) -> isize {
let effect = self.value;
// -- snip --
effect
}
}
#[derive(Deserialize, PartialEq, Debug)]
struct Scroll {
#[serde(rename = "kind", deserialize_with = "deserialize_effect")]
effect: isize,
}
fn deserialize_effect<'de, D>(deserializer: D) -> Result<isize, D::Error>
where
D: Deserializer<'de>,
{
let kind = String::deserialize(deserializer)?;
Ok(MAGICK_BOOK.with(|book| book.borrow().find(&kind)))
}
#[test]
fn test_deserialize() {
MAGICK_BOOK.with(|book| book.borrow_mut().value = 42);
let scroll: Scroll = serde_json::from_str(r#"{"kind":"wind"}"#).unwrap();
assert_eq!(scroll, Scroll { effect: 42 });
}

How to extend a function of a protocol in swift 3?

I have following code:
protocol Protocol_1 {
var prop_1: String { get set }
var prop_2: Int { get set }
}
protocol Protocol_2 {
var prop_3: Double { get set }
var prop_4: Bool { get set }
}
extension Protocol_1 {
mutating func set<T>(value: T, forKey key: String)
{
switch key {
case "prop_1":
if value is String {
prop_1 = value as! String
}
case "prop_2":
if value is Int {
prop_2 = value as! Int
}
default:
break
}
}
}
extension Protocol_2 {
mutating func set<T>(value: T, forKey key: String)
{
switch key {
case "prop_3":
if value is Double {
prop_3 = value as! Double
}
case "prop_4":
if value is Bool {
prop_4 = value as! Bool
}
default:
break
}
}
}
struct MyStruct : Protocol_1, Protocol_2 {
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
}
var myStruct = MyStruct(prop_1: "hello", prop_2: 0, prop_3: 3.5, prop_4: true)
myStruct.set(value: "bye", forKey: "prop_1")
Now the playground gives me an error because it is not clear what set function should be called. Playground execution failed: error: ProtocolsPlayground.playground:59:1: error: ambiguous use of 'set(value:forKey:)'
myStruct.set(value: "bye", forKey: "prop_1")
This is clear but how can I achieve such function extension or is there a work around? Especially if the Protocol_1 is not editable.
I don't know of any way to extend an existing function or another protocol's function using a protocol.
What I would suggest is that you separate the mechanism that assigns properties by name from the two protocols using a third protocol that does that specifically and separately.
Here's one way to approach this:
Define a class that will handle getting and setting properties based on a mapping between names (keys) and variable references:
class PropertyMapper
{
static var sharedGetter = PropertyMapperGet()
static var sharedSetter = PropertyMapperSet()
var value : Any = 0
var success = false
var key = ""
func map<T>(_ key:String, _ variable:inout T) {}
func clear()
{
value = 0
success = false
key = ""
}
}
class PropertyMapperGet:PropertyMapper
{
func get(forKey:String)
{
key = forKey
success = false
}
override func map<T>(_ key:String, _ variable:inout T)
{
if !success && self.key == key
{
value = variable
success = true
}
}
}
class PropertyMapperSet:PropertyMapper
{
override func map<T>(_ key:String, _ variable:inout T)
{
if !success && self.key == key,
let newValue = value as? T
{
variable = newValue
success = true
}
}
func set(value newValue:Any, forKey:String)
{
key = forKey
value = newValue
success = false
}
}
Then, you can define a protocol for all struct and classes that will have the ability to assign their properties by name (key):
protocol MappedProperties
{
mutating func mapProperties(_ :PropertyMapper)
}
extension MappedProperties
{
mutating func get(_ key:String) -> Any?
{
let mapper = PropertyMapper.sharedGetter
defer { mapper.clear() }
mapper.get(forKey:key)
mapProperties(mapper)
return mapper.success ? mapper.value : nil
}
#discardableResult
mutating func set(value:Any, forKey key:String) -> Bool
{
let mapper = PropertyMapper.sharedSetter
defer { mapper.clear() }
mapper.set(value:value, forKey:key)
mapProperties(mapper)
return mapper.success
}
}
Your protocols can require that the struct that adopt them offer the named assignments. (see farther down for making the property mapping part of your protocol)
protocol Protocol_1:MappedProperties
{
var prop_1: String { get set }
var prop_2: Int { get set }
}
protocol Protocol_2:MappedProperties
{
var prop_3: Double { get set }
var prop_4: Bool { get set }
}
Your struct will need to implement the property mapping in order to adopt your protocols. The key/variable mapping is performed in a centralized function for the whole struct and needs to provide keys for all the variables in both protocols.
struct MyStruct : Protocol_1, Protocol_2
{
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
mutating func mapProperties(_ mapper:PropertyMapper)
{
mapper.map("prop_1", &prop_1)
mapper.map("prop_2", &prop_2)
mapper.map("prop_3", &prop_3)
mapper.map("prop_4", &prop_4)
}
}
This allows the struct to assign properties by name (key):
var myStruct = MyStruct(prop_1: "hello", prop_2: 0, prop_3: 3.5, prop_4: true)
myStruct.set(value: "bye", forKey: "prop_1")
To refine this further and make the property mapping part of your protocols, you can add a mapping function to the protocol so that the structs that adopt it don't have to know the details of this mapping.
They will still need to implement the mapping protocol's function but they can simply use functions provided by your protocols to do the job.
For example( I only showed Protocol_1 but you can do it with both of them):
extension Protocol_1
{
mutating func mapProtocol_1(_ mapper:PropertyMapper)
{
mapper.map("prop_1", &prop_1)
mapper.map("prop_2", &prop_2)
}
}
With the function provided by the protocol, the struct doesn't need to know which properties are mapped. This should make maintenance of the structs and protocols less error prone and avoid duplications.
struct MyStruct : Protocol_1, Protocol_2
{
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
mutating func mapProperties(_ mapper:PropertyMapper)
{
mapProtocol_1(mapper)
mapper.map("prop_3", &prop_3)
mapper.map("prop_4", &prop_4)
}
}

Compare `Foo<i32>` and `Foo<u32>`

Need realize the possibility of comparison Foo<i32> and Foo<u32>.
struct Foo<T> {
id: usize,
data: T
}
impl<T> Foo<T> {
fn new_i32(i: i32) -> Foo<i32> {
Foo {
id: 0,
data: i
}
}
fn new_u32(u: u32) -> Foo<u32> {
Foo {
id: 1,
data: u
}
}
}
The problem is that trait PartialEq can only compare the same types.
impl<T> PartialEq for Foo<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
And this dont work:
let a = Foo::new_u32(123);
let b = Foo::new_i32(123);
println!("{}", a == b);
Full code in play.rust-lang.org
The problem is that trait PartialEq can only compare the same types.
That's not true. It just defaults the Rhs to the same type as Self:
pub trait PartialEq<Rhs = Self> where Rhs: ?Sized {
...
}
Here's how you would implement PartialEq for Foo<L> and Foo<R> for any L and R:
impl<L, R> PartialEq<Foo<R>> for Foo<L> {
fn eq(&self, other: &Foo<R>) -> bool {
self.id == other.id
}
}
Note that I also had to change the impl block to fix some type inference errors. Final code:
struct Foo<T> {
id: usize,
data: T,
}
impl Foo<i32> {
fn new_i32(i: i32) -> Foo<i32> {
Foo { id: 0, data: i }
}
}
impl Foo<u32> {
fn new_u32(u: u32) -> Foo<u32> {
Foo { id: 1, data: u }
}
}
impl<L, R> PartialEq<Foo<R>> for Foo<L> {
fn eq(&self, other: &Foo<R>) -> bool {
self.id == other.id
}
}
fn main() {
let a = Foo::new_u32(123);
let b = Foo::new_i32(123);
println!("{}", a == b);
}
Output:
false
https://play.rust-lang.org/?gist=51166880a9ab0c49d7650588c4ed8290&version=stable&backtrace=0