diff options
author | Haibo Huang <hhb@google.com> | 2020-08-11 23:25:13 -0700 |
---|---|---|
committer | Chih-Hung Hsieh <chh@google.com> | 2020-08-17 16:10:23 -0700 |
commit | 6f3fa15012d300a886add4bacbd8ad2267abee28 (patch) | |
tree | 3c6efb31bc3e28bdbfe31f8a2bebecc953aed3a5 /src | |
parent | c2da9b8c19fae2731e052f8c4bbda9ad12452457 (diff) | |
download | lazycell-6f3fa15012d300a886add4bacbd8ad2267abee28.tar.gz |
Upgrade rust/crates/lazycell to 1.3.0
* Keep Android local change in src/lib.rs.
// ANDROID: Unconditionally use std to allow building as a dylib.
extern crate std;
Change-Id: Iffb11ce26acde2ae512502957ac87b3e430fe673
Test: make
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 45 | ||||
-rw-r--r-- | src/serde_impl.rs | 86 |
2 files changed, 125 insertions, 6 deletions
@@ -1,5 +1,5 @@ // Original work Copyright (c) 2014 The Rust Project Developers -// Modified work Copyright (c) 2016-2018 Nikita Pekin and the lazycell contributors +// Modified work Copyright (c) 2016-2020 Nikita Pekin and the lazycell contributors // See the README.md file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or @@ -44,9 +44,16 @@ //! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell` //! is that after it is initialized, it can't be modified. + // ANDROID: Unconditionally use std to allow building as a dylib. +#[cfg(not(test))] #[macro_use] extern crate std; +#[cfg(feature = "serde")] +extern crate serde; + +#[cfg(feature = "serde")] +mod serde_impl; use std::cell::UnsafeCell; use std::mem; @@ -57,7 +64,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; /// A `LazyCell` is completely frozen once filled, **unless** you have `&mut` /// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the /// contents. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct LazyCell<T> { inner: UnsafeCell<Option<T>>, } @@ -70,12 +77,13 @@ impl<T> LazyCell<T> { /// Put a value into this cell. /// - /// This function will return `Err(value)` is the cell is already full. + /// This function will return `Err(value)` if the cell is already full. pub fn fill(&self, value: T) -> Result<(), T> { - let slot = unsafe { &mut *self.inner.get() }; + let slot = unsafe { &*self.inner.get() }; if slot.is_some() { return Err(value); } + let slot = unsafe { &mut *self.inner.get() }; *slot = Some(value); Ok(()) @@ -214,6 +222,12 @@ impl<T: Copy> LazyCell<T> { } } +impl<T> Default for LazyCell<T> { + fn default() -> Self { + Self::new() + } +} + impl <T: Clone> Clone for LazyCell<T> { /// Create a clone of this `LazyCell` /// @@ -231,7 +245,7 @@ const LOCK: usize = 1; const SOME: usize = 2; /// A lazily filled and thread-safe `Cell`, with frozen contents. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct AtomicLazyCell<T> { inner: UnsafeCell<Option<T>>, state: AtomicUsize, @@ -251,7 +265,7 @@ impl<T> AtomicLazyCell<T> { /// Put a value into this cell. /// - /// This function will return `Err(value)` is the cell is already full. + /// This function will return `Err(value)` if the cell is already full. pub fn fill(&self, t: T) -> Result<(), T> { if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) { return Err(t); @@ -324,6 +338,12 @@ impl<T: Copy> AtomicLazyCell<T> { } } +impl<T> Default for AtomicLazyCell<T> { + fn default() -> Self { + Self::new() + } +} + impl<T: Clone> Clone for AtomicLazyCell<T> { /// Create a clone of this `AtomicLazyCell` /// @@ -645,4 +665,17 @@ mod tests { assert_eq!(clone2.borrow(), Some(&4)); assert_eq!(cell.borrow(), Some(&2)); } + + #[test] + fn default() { + #[derive(Default)] + struct Defaultable; + struct NonDefaultable; + + let _: LazyCell<Defaultable> = LazyCell::default(); + let _: LazyCell<NonDefaultable> = LazyCell::default(); + + let _: AtomicLazyCell<Defaultable> = AtomicLazyCell::default(); + let _: AtomicLazyCell<NonDefaultable> = AtomicLazyCell::default(); + } } diff --git a/src/serde_impl.rs b/src/serde_impl.rs new file mode 100644 index 0000000..8f08f7b --- /dev/null +++ b/src/serde_impl.rs @@ -0,0 +1,86 @@ +// Copyright (c) 2020 Nikita Pekin and the lazycell contributors +// See the README.md file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms.use serde::ser::{Serialize, Serializer}; +use serde::ser::{Serialize, Serializer}; +use serde::de::{self, Deserialize, Deserializer, Visitor}; + +use std::fmt; +use std::marker::PhantomData; + +use super::{LazyCell, AtomicLazyCell}; + +impl<T: Serialize> Serialize for LazyCell<T> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self.borrow() { + Some(val) => serializer.serialize_some(val), + None => serializer.serialize_none() + } + } +} + + +impl<T: Serialize> Serialize for AtomicLazyCell<T> { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + match self.borrow() { + Some(val) => serializer.serialize_some(val), + None => serializer.serialize_none() + } + } +} + +struct LazyCellVisitor<T>(PhantomData<*const T>); +impl<'de, T: Deserialize<'de>> Visitor<'de> for LazyCellVisitor<T> { + type Value = LazyCell<T>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a LazyCell") + } + + fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> { + let mut cell = LazyCell::new(); + cell.replace(T::deserialize(deserializer)?); + Ok(cell) + } + + fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> { + Ok(LazyCell::new()) + } +} + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for LazyCell<T> { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_option(LazyCellVisitor(PhantomData)) + } +} + + +struct AtomicLazyCellVisitor<T>(PhantomData<*const T>); +impl<'de, T: Deserialize<'de>> Visitor<'de> for AtomicLazyCellVisitor<T> { + type Value = AtomicLazyCell<T>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an AtomicLazyCell") + } + + fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> { + let mut cell = AtomicLazyCell::new(); + cell.replace(T::deserialize(deserializer)?); + Ok(cell) + } + + fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> { + Ok(AtomicLazyCell::new()) + } +} + + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for AtomicLazyCell<T> { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + deserializer.deserialize_option(AtomicLazyCellVisitor(PhantomData)) + } +} |