Skip to content

Commit f7cb667

Browse files
committed
Introduce container for default values
1 parent 621340d commit f7cb667

File tree

2 files changed

+166
-7
lines changed

2 files changed

+166
-7
lines changed

src/trace/implementations/mod.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub use self::merge_batcher::MergeBatcher as Batcher;
4848
pub mod ord_neu;
4949
pub mod rhh;
5050
pub mod huffman_container;
51+
pub mod option_container;
5152

5253
// Opinionated takes on default spines.
5354
pub use self::ord_neu::OrdValSpine as ValSpine;
@@ -320,7 +321,7 @@ pub mod containers {
320321

321322
use timely::container::columnation::{Columnation, TimelyStack};
322323

323-
use std::borrow::{Borrow, ToOwned};
324+
use std::borrow::ToOwned;
324325
use crate::trace::MyTrait;
325326

326327
/// A general-purpose container resembling `Vec<T>`.
@@ -332,13 +333,21 @@ pub mod containers {
332333
/// The type that can be read back out of the container.
333334
type ReadItem<'a>: Copy + MyTrait<'a, Owned = Self::PushItem> + for<'b> PartialOrd<Self::ReadItem<'b>>;
334335
/// Inserts an owned item.
335-
fn push(&mut self, item: Self::PushItem);
336+
fn push(&mut self, item: Self::PushItem) {
337+
self.copy_push(&item);
338+
}
336339
/// Inserts an owned item.
337-
fn copy_push(&mut self, item: &Self::PushItem);
340+
fn copy_push(&mut self, item: &Self::PushItem) {
341+
self.copy(MyTrait::borrow_as(item));
342+
}
338343
/// Inserts a borrowed item.
339344
fn copy(&mut self, item: Self::ReadItem<'_>);
340345
/// Extends from a range of items in another`Self`.
341-
fn copy_range(&mut self, other: &Self, start: usize, end: usize);
346+
fn copy_range(&mut self, other: &Self, start: usize, end: usize) {
347+
for index in start .. end {
348+
self.copy(other.index(index));
349+
}
350+
}
342351
/// Creates a new container with sufficient capacity.
343352
fn with_capacity(size: usize) -> Self;
344353
/// Creates a new container with sufficient capacity.
@@ -357,6 +366,8 @@ pub mod containers {
357366
None
358367
}
359368
}
369+
/// Indicates if the length is zero.
370+
fn is_empty(&self) -> bool { self.len() == 0 }
360371

361372
/// Reports the number of elements satisfing the predicate.
362373
///
@@ -441,9 +452,6 @@ pub mod containers {
441452
type PushItem = T;
442453
type ReadItem<'a> = &'a Self::PushItem;
443454

444-
fn push(&mut self, item: Self::PushItem) {
445-
self.copy(item.borrow());
446-
}
447455
fn copy_push(&mut self, item: &Self::PushItem) {
448456
self.copy(item);
449457
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
//! A container optimized for identical contents.
2+
3+
use crate::trace::cursor::MyTrait;
4+
use crate::trace::implementations::BatchContainer;
5+
6+
/// A container that effectively represents default values.
7+
///
8+
/// This container is meant to be a minimal non-trivial container,
9+
/// and may be useful in unifying `OrdVal` and `OrdKey` spines.
10+
struct OptionContainer<C> {
11+
/// Number of default items pushed.
12+
defaults: usize,
13+
/// Spill-over for non-empty rows.
14+
container: C,
15+
}
16+
17+
impl<C> BatchContainer for OptionContainer<C>
18+
where
19+
C: BatchContainer,
20+
C::PushItem: Default + Ord,
21+
{
22+
type PushItem = C::PushItem;
23+
type ReadItem<'a> = OptionWrapper<'a, C>;
24+
25+
fn push(&mut self, item: Self::PushItem) {
26+
if item == Default::default() && self.container.is_empty() {
27+
self.defaults += 1;
28+
}
29+
else {
30+
self.container.push(item)
31+
}
32+
}
33+
fn copy<'a>(&mut self, item: Self::ReadItem<'a>) {
34+
if item.equals(&Default::default()) && self.container.is_empty() {
35+
self.defaults += 1;
36+
}
37+
else {
38+
if let Some(item) = item.inner {
39+
self.container.copy(item);
40+
}
41+
else {
42+
self.container.push(Default::default());
43+
}
44+
}
45+
}
46+
fn with_capacity(size: usize) -> Self {
47+
Self {
48+
defaults: 0,
49+
container: C::with_capacity(size),
50+
}
51+
}
52+
fn merge_capacity(cont1: &Self, cont2: &Self) -> Self {
53+
Self {
54+
defaults: 0,
55+
container: C::merge_capacity(&cont1.container, &cont2.container),
56+
}
57+
}
58+
fn index(&self, index: usize) -> Self::ReadItem<'_> {
59+
if index < self.defaults {
60+
OptionWrapper { inner: None }
61+
}
62+
else {
63+
OptionWrapper { inner: Some(self.container.index(index - self.defaults))}
64+
}
65+
}
66+
fn len(&self) -> usize {
67+
self.container.len() + self.defaults
68+
}
69+
}
70+
71+
/// A read wrapper that presents as
72+
struct OptionWrapper<'a, C: BatchContainer> {
73+
inner: Option<C::ReadItem<'a>>,
74+
}
75+
76+
impl<'a, C: BatchContainer> Copy for OptionWrapper<'a, C> { }
77+
impl<'a, C: BatchContainer> Clone for OptionWrapper<'a, C> {
78+
fn clone(&self) -> Self { *self }
79+
}
80+
81+
82+
use std::cmp::Ordering;
83+
impl<'a, 'b, C: BatchContainer> PartialEq<OptionWrapper<'a, C>> for OptionWrapper<'b, C>
84+
where
85+
C::PushItem: Default + Ord,
86+
{
87+
fn eq(&self, other: &OptionWrapper<'a, C>) -> bool {
88+
match (&self.inner, &other.inner) {
89+
(None, None) => true,
90+
(None, Some(item2)) => item2.equals(&Default::default()),
91+
(Some(item1), None) => item1.equals(&Default::default()),
92+
(Some(item1), Some(item2)) => item1.eq(item2)
93+
}
94+
}
95+
}
96+
impl<'a, C: BatchContainer> Eq for OptionWrapper<'a, C> where
97+
C::PushItem: Default + Ord
98+
{ }
99+
impl<'a, 'b, C: BatchContainer> PartialOrd<OptionWrapper<'a, C>> for OptionWrapper<'b, C> where
100+
C::PushItem: Default + Ord,
101+
{
102+
fn partial_cmp(&self, other: &OptionWrapper<'a, C>) -> Option<Ordering> {
103+
let default = Default::default();
104+
match (&self.inner, &other.inner) {
105+
(None, None) => Some(Ordering::Equal),
106+
(None, Some(item2)) => item2.partial_cmp(&C::ReadItem::<'_>::borrow_as(&default)).map(|x| x.reverse()),
107+
(Some(item1), None) => item1.partial_cmp(&C::ReadItem::<'_>::borrow_as(&default)),
108+
(Some(item1), Some(item2)) => item1.partial_cmp(item2)
109+
}
110+
}
111+
}
112+
impl<'a, C: BatchContainer> Ord for OptionWrapper<'a, C> where
113+
C::PushItem: Default + Ord,
114+
{
115+
fn cmp(&self, other: &Self) -> Ordering {
116+
self.partial_cmp(other).unwrap()
117+
}
118+
}
119+
120+
121+
impl<'a, C: BatchContainer> MyTrait<'a> for OptionWrapper<'a, C>
122+
where
123+
C::PushItem : Default + Ord,
124+
{
125+
type Owned = C::PushItem;
126+
127+
fn into_owned(self) -> Self::Owned {
128+
self.inner.map(|r| r.into_owned()).unwrap_or_else(Default::default)
129+
}
130+
fn clone_onto(&self, other: &mut Self::Owned) {
131+
if let Some(item) = &self.inner {
132+
item.clone_onto(other)
133+
}
134+
else {
135+
*other = Default::default();
136+
}
137+
}
138+
fn compare(&self, other: &Self::Owned) -> std::cmp::Ordering {
139+
if let Some(item) = &self.inner {
140+
item.compare(other)
141+
}
142+
else {
143+
<C::PushItem>::default().cmp(other)
144+
}
145+
}
146+
fn borrow_as(other: &'a Self::Owned) -> Self {
147+
Self {
148+
inner: Some(<_>::borrow_as(other))
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)