Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![deny(
- elided_lifetimes_in_paths,
- )]
- #![allow(
- dead_code,
- )]
- // 0.4.6
- use ::chrono::*;
- mod lib {
- use core::{*,
- marker::PhantomPinned as PinSensitive,
- pin::Pin,
- };
- #[derive(Debug)]
- pub
- struct Location {
- pub
- name: String,
- }
- #[repr(transparent)]
- pub
- struct PinSensitiveLocation {
- location: Location,
- _pin_sensitive: PinSensitive,
- }
- impl ops::Deref for PinSensitiveLocation {
- type Target = Location;
- fn deref (self: &'_ Self) -> &'_ Self::Target
- {
- &self.location
- }
- }
- impl fmt::Debug for PinSensitiveLocation {
- fn fmt (
- self: &'_ Self,
- stream: &'_ mut fmt::Formatter<'_>,
- ) -> fmt::Result
- {
- // write!(stream, "PinSensitive")?;
- fmt::Debug::fmt(&self.location, stream)
- }
- }
- #[derive(Debug)]
- pub
- struct Locations /* = */ (
- pub
- Vec<Location>
- );
- #[derive(Debug)]
- pub
- struct PinnedLocations /* = */ (
- Pin<Box< [PinSensitiveLocation] >>
- );
- impl PinnedLocations {
- pub
- fn get (
- self: &'_ Self,
- index: usize,
- ) -> Option< Pin<&'_ PinSensitiveLocation> >
- {
- if index < self.0.len() {
- Some(unsafe {
- // safety: index / field access is a valid pin projection
- self.0
- .as_ref()
- .map_unchecked(move |locations| locations.get_unchecked(index))
- })
- } else {
- None
- }
- }
- }
- impl Locations {
- pub
- fn pinned (self: Self) -> PinnedLocations
- {
- let mut boxed_locations: Box<[Location]> = self.0.into_boxed_slice();
- let pinned_locations: Box<[PinSensitiveLocation]> = unsafe {
- // Safety: PinSensitiveLocation is #[repr(transparent)]
- let (len, ptr): (usize, *mut PinSensitiveLocation) = (
- boxed_locations.len(),
- boxed_locations.as_mut_ptr() as *mut PinSensitiveLocation,
- );
- mem::forget(boxed_locations);
- Box::from_raw(
- slice::from_raw_parts_mut(
- ptr,
- len,
- )
- )
- };
- PinnedLocations(pinned_locations.into())
- }
- }
- #[derive(Debug)]
- pub
- struct Event<'loc> {
- pub
- name: String,
- pub
- occurrences: Vec<Occurrence<'loc>>,
- }
- #[derive(
- Debug,
- // ensures there is no drop glue:
- // `WithEvents` transmute requires that the &'loc reference must not be dereferenced when dropped
- Clone, Copy,
- )]
- pub
- struct Occurrence<'loc> {
- pub
- start: ::chrono::NaiveDateTime,
- pub
- location: Pin<&'loc PinSensitiveLocation>,
- }
- #[derive(Debug)]
- pub
- struct Store {
- pub
- locations: PinnedLocations,
- events: Vec<Event<'static>>,
- }
- impl Store {
- pub
- fn events (
- self: &'_ Self,
- ) -> &'_ Vec<Event<'_>>
- {
- &self.events
- }
- /// API to allow mutation and adding events
- /// (reconstructing the Store is needed)
- pub
- fn get_locations_and_take_events (
- self: &'_ mut Self,
- ) -> (&'_ PinnedLocations, Vec<Event<'_>>)
- {
- (&self.locations, mem::replace(&mut self.events, Vec::default()))
- }
- }
- impl Store {
- pub
- fn with_events (
- events: Vec<Event<'_>>,
- ) -> WithEvents
- {
- // safety:
- // - no public non-`unsafe` API
- // - Event : Copy thus drop does not deref
- unsafe {
- WithEvents(mem::transmute(events))
- }
- }
- }
- pub
- struct WithEvents /* = */ (
- /// has to be private
- Vec<Event<'static>>
- );
- impl WithEvents {
- /// # Safety
- ///
- /// the given `events` must refer to the input `locations` only
- pub
- unsafe fn and_locations (
- self: Self,
- locations: PinnedLocations,
- ) -> Store
- {
- let WithEvents(events) = self;
- Store {
- locations,
- events,
- }
- }
- }
- }
- use lib::*;
- fn main ()
- {
- let bar = Location {
- name: String::from("Some bar"),
- };
- let foo = Location {
- name: String::from("Some foo"),
- };
- let locations = Locations(vec![bar, foo]).pinned();
- let events = vec![Event {
- name: "Social Dance".into(),
- occurrences: vec![Occurrence {
- start: NaiveDate::from_ymd(2019, 4, 1).and_hms(20, 30, 00),
- location: locations.get(0).unwrap(),
- }],
- }];
- let mut store = unsafe {
- // safety: it is indeed from `locations` that `events` does borrow
- Store::with_events(events)
- .and_locations(locations)
- };
- dbg!(&store);
- // Adding an event afterwards
- let (locations, mut events) = store.get_locations_and_take_events();
- let start = NaiveDate::from_ymd(2019, 4, 1).and_hms(20, 30, 00);
- events.push(Event {
- name: "Pin-pong".into(),
- occurrences: vec![
- Occurrence { start, location: locations.get(0).unwrap(), },
- Occurrence { start, location: locations.get(1).unwrap(), },
- ],
- });
- let store_events = Store::with_events(events);
- let Store { locations, .. } = store;
- let store = unsafe {
- // safety: it is indeed from `locations` that `events` does borrow
- store_events.and_locations(locations)
- };
- dbg!(&store);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement