compact/
compact_option.rs1use super::compact::Compact;
2
3#[derive(Clone, Default, Debug)]
7pub struct CompactOption<T: Compact + Clone>(pub Option<T>);
8
9impl<T: Compact + Clone> ::std::ops::Deref for CompactOption<T> {
10 type Target = Option<T>;
11
12 fn deref(&self) -> &Option<T> {
13 &self.0
14 }
15}
16
17impl<T: Compact + Clone> ::std::ops::DerefMut for CompactOption<T> {
18 fn deref_mut(&mut self) -> &mut Option<T> {
19 &mut self.0
20 }
21}
22
23impl<T: Clone + Compact> Compact for CompactOption<T> {
24 fn is_still_compact(&self) -> bool {
25 self.0
26 .as_ref()
27 .map(|t| t.is_still_compact())
28 .unwrap_or(true)
29 }
30
31 fn dynamic_size_bytes(&self) -> usize {
32 self.0.as_ref().map(|t| t.dynamic_size_bytes()).unwrap_or(0)
33 }
34
35 unsafe fn compact(source: *mut Self, dest: *mut Self, new_dynamic_part: *mut u8) {
36 if let CompactOption(Some(ref mut s)) = *source {
37 ::std::ptr::copy_nonoverlapping(source, dest, 1);
38 if let CompactOption(Some(ref mut d)) = *dest {
39 Compact::compact(s, d, new_dynamic_part);
40 } else {
41 unreachable!()
42 }
43 } else {
44 ::std::ptr::write(dest, CompactOption(None));
45 }
46 }
47
48 unsafe fn decompact(source: *const Self) -> Self {
49 if let CompactOption(Some(ref s)) = *source {
50 CompactOption(Some(Compact::decompact(s)))
51 } else {
52 CompactOption(None)
53 }
54 }
55}
56
57#[cfg(feature = "serde-serialization")]
58use std::marker::PhantomData;
59
60#[cfg(feature = "serde-serialization")]
61impl<T: Compact + ::serde::ser::Serialize> ::serde::ser::Serialize for CompactOption<T> {
62 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
63 where
64 S: ::serde::ser::Serializer,
65 {
66 match self.0 {
67 Some(ref value) => serializer.serialize_some(value),
68 None => serializer.serialize_none(),
69 }
70 }
71}
72
73#[cfg(feature = "serde-serialization")]
74struct CompactOptionVisitor<T: Compact> {
75 marker: PhantomData<fn() -> CompactOption<T>>,
76}
77
78#[cfg(feature = "serde-serialization")]
79impl<T: Compact> CompactOptionVisitor<T> {
80 fn new() -> Self {
81 CompactOptionVisitor {
82 marker: PhantomData,
83 }
84 }
85}
86
87#[cfg(feature = "serde-serialization")]
88impl<'de, T: Compact + ::serde::de::Deserialize<'de>> ::serde::de::Visitor<'de>
89 for CompactOptionVisitor<T>
90{
91 type Value = CompactOption<T>;
92
93 fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
94 formatter.write_str("An option")
95 }
96
97 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
98 where
99 D: ::serde::de::Deserializer<'de>,
100 {
101 Ok(CompactOption(Some(T::deserialize(deserializer)?)))
102 }
103
104 fn visit_none<E>(self) -> Result<Self::Value, E>
105 where
106 E: ::serde::de::Error,
107 {
108 Ok(CompactOption(None))
109 }
110}
111
112#[cfg(feature = "serde-serialization")]
113impl<'de, T: Compact + ::serde::de::Deserialize<'de>> ::serde::de::Deserialize<'de>
114 for CompactOption<T>
115{
116 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117 where
118 D: ::serde::de::Deserializer<'de>,
119 {
120 deserializer.deserialize_option(CompactOptionVisitor::new())
121 }
122}
123
124#[test]
125fn basic_option() {
126 use super::compact_vec::CompactVec;
127 use super::simple_allocator_trait::{Allocator, DefaultHeap};
128 let mut option: CompactOption<CompactVec<u32>> = CompactOption(Some(CompactVec::new()));
129
130 if let Some(ref mut list) = *option {
131 list.push(1);
132 list.push(2);
133 list.push(3);
134 assert_eq!(&[1, 2, 3], &**list);
135 } else {
136 unreachable!()
137 }
138
139 let bytes = option.total_size_bytes();
140 let storage = DefaultHeap::allocate(bytes);
141
142 unsafe {
143 Compact::compact_behind(&mut option, storage as *mut CompactOption<CompactVec<u32>>);
144 ::std::mem::forget(option);
145 if let Some(ref list) = **(storage as *mut CompactOption<CompactVec<u32>>) {
146 assert_eq!(&[1, 2, 3], &**list);
147 } else {
148 unreachable!()
149 }
150 println!("before decompact!");
151 if let Some(ref list) = *Compact::decompact(storage as *mut CompactOption<CompactVec<u32>>)
152 {
153 assert_eq!(&[1, 2, 3], &**list);
154 } else {
155 unreachable!()
156 }
157 DefaultHeap::deallocate(storage, bytes);
158 }
159}