Skip to content

Commit 4a122a3

Browse files
committed
Updated maybe_owned_vec with review feedback.
Namely: * Added conversion traits both to and from the various vector types, analogous to how `str::MaybeOwned` works with `str::IntoMaybeOwned` and `str::Str`. This led me to add the `FixedLen` variant of `MaybeOwnedVector` for interoperability with `std::slice`. * Revised client example code to make use of `into_maybe_owned` * Added implementations of `Show` and `CloneableVector` for `MaybeOwnedVector`. * As suggested by kballard, added `into_vec` method that is analogous to `CloneableVector::into_owned` except it produces a `Vec` rather than a `~[T]`.
1 parent b737418 commit 4a122a3

File tree

2 files changed

+96
-26
lines changed

2 files changed

+96
-26
lines changed

src/libgraphviz/lib.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
/*! Generate files suitable for use with [Graphviz](http://www.graphviz.org/)
1212
13-
The `render` function generates output (e.g. a `output.dot` file) for
13+
The `render` function generates output (e.g. an `output.dot` file) for
1414
use with [Graphviz](http://www.graphviz.org/) by walking a labelled
1515
graph. (Graphviz can then automatically lay out the nodes and edges
1616
of the graph, and also optionally render the graph as an image or
@@ -37,16 +37,18 @@ pairs of ints, representing the edges (the node set is implicit).
3737
Each node label is derived directly from the int representing the node,
3838
while the edge labels are all empty strings.
3939
40-
This example also illustrates how to use the `Borrowed` variant of
41-
`MaybeOwnedVector` to return a slice into the edge list, rather than
42-
constructing a copy from scratch.
40+
This example also illustrates how to use `MaybeOwnedVector` to return
41+
an owned vector or a borrowed slice as appropriate: we construct the
42+
node vector from scratch, but borrow the edge list (rather than
43+
constructing a copy of all the edges from scratch).
4344
4445
The output from this example renders five nodes, with the first four
4546
forming a diamond-shaped acyclic graph and then pointing to the fifth
4647
which is cyclic.
4748
4849
```rust
4950
use dot = graphviz;
51+
use graphviz::maybe_owned_vec::IntoMaybeOwnedVector;
5052
5153
type Nd = int;
5254
type Ed = (int,int);
@@ -77,12 +79,12 @@ impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges {
7779
}
7880
nodes.sort();
7981
nodes.dedup();
80-
nodes.move_iter().collect()
82+
nodes.into_maybe_owned()
8183
}
8284
8385
fn edges(&'a self) -> dot::Edges<'a,Ed> {
8486
let &Edges(ref edges) = self;
85-
dot::maybe_owned_vec::Borrowed(edges.as_slice())
87+
edges.as_slice().into_maybe_owned()
8688
}
8789
8890
fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
@@ -119,9 +121,16 @@ This example also illustrates how to use a type (in this case the edge
119121
type) that shares substructure with the graph: the edge type here is a
120122
direct reference to the `(source,target)` pair stored in the graph's
121123
internal vector (rather than passing around a copy of the pair
122-
itself). Note that in this case, this implies that `fn edges(&'a
123-
self)` must construct a fresh `Vec<&'a (uint,uint)>` from the
124-
`Vec<(uint,uint)>` edges stored in `self`.
124+
itself). Note that this implies that `fn edges(&'a self)` must
125+
construct a fresh `Vec<&'a (uint,uint)>` from the `Vec<(uint,uint)>`
126+
edges stored in `self`.
127+
128+
Since both the set of nodes and the set of edges are always
129+
constructed from scratch via iterators, we use the `collect()` method
130+
from the `Iterator` trait to collect the nodes and edges into freshly
131+
constructed growable `Vec` values (rather use the `into_maybe_owned`
132+
from the `IntoMaybeOwnedVector` trait as was used in the first example
133+
above).
125134
126135
The output from this example renders four nodes that make up the
127136
Hasse-diagram for the subsets of the set `{x, y}`. Each edge is

src/libgraphviz/maybe_owned_vec.rs

+78-17
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,69 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::container::Container;
11+
use std::fmt;
1212
use std::iter::FromIterator;
1313
use std::slice;
1414

15-
// Note: Once Dynamically Sized Types (DST) lands, this should be
16-
// replaced with something like `enum Owned<'a, Sized? U>{ Owned(~U),
17-
// Borrowed(&'a U) }`; and then `U` could be instantiated with `[T]`
18-
// or `str`, etc.
15+
// Note 1: It is not clear whether the flexibility of providing both
16+
// the `Growable` and `FixedLen` variants is sufficiently useful.
17+
// Consider restricting to just a two variant enum.
1918

20-
/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>` and `&'a [T]`.
19+
// Note 2: Once Dynamically Sized Types (DST) lands, it might be
20+
// reasonable to replace this with something like `enum MaybeOwned<'a,
21+
// Sized? U>{ Owned(~U), Borrowed(&'a U) }`; and then `U` could be
22+
// instantiated with `[T]` or `str`, etc. Of course, that would imply
23+
// removing the `Growable` variant, which relates to note 1 above.
24+
// Alternatively, we might add `MaybeOwned` for the general case but
25+
// keep some form of `MaybeOwnedVector` to avoid unnecessary copying
26+
// of the contents of `Vec<T>`, since we anticipate that to be a
27+
// frequent way to dynamically construct a vector.
28+
29+
/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `~[T]`, `&'a [T]`.
2130
///
2231
/// Some clients will have a pre-allocated vector ready to hand off in
2332
/// a slice; others will want to create the set on the fly and hand
24-
/// off ownership.
25-
#[deriving(Eq)]
33+
/// off ownership, via either `Growable` or `FixedLen` depending on
34+
/// which kind of vector they have constucted. (The `FixedLen`
35+
/// variant is provided for interoperability with `std::slice` methods
36+
/// that return `~[T]`.)
2637
pub enum MaybeOwnedVector<'a,T> {
2738
Growable(Vec<T>),
39+
FixedLen(~[T]),
2840
Borrowed(&'a [T]),
2941
}
3042

43+
/// Trait for moving into a `MaybeOwnedVector`
44+
pub trait IntoMaybeOwnedVector<'a,T> {
45+
/// Moves self into a `MaybeOwnedVector`
46+
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
47+
}
48+
49+
impl<'a,T> IntoMaybeOwnedVector<'a,T> for Vec<T> {
50+
#[inline]
51+
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
52+
}
53+
54+
impl<'a,T> IntoMaybeOwnedVector<'a,T> for ~[T] {
55+
#[inline]
56+
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { FixedLen(self) }
57+
}
58+
59+
impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
60+
#[inline]
61+
fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
62+
}
63+
3164
impl<'a,T> MaybeOwnedVector<'a,T> {
3265
pub fn iter(&'a self) -> slice::Items<'a,T> {
3366
match self {
3467
&Growable(ref v) => v.iter(),
68+
&FixedLen(ref v) => v.iter(),
3569
&Borrowed(ref v) => v.iter(),
3670
}
3771
}
3872
}
3973

40-
impl<'a,T> Container for MaybeOwnedVector<'a,T> {
41-
fn len(&self) -> uint {
42-
match self {
43-
&Growable(ref v) => v.len(),
44-
&Borrowed(ref v) => v.len(),
45-
}
46-
}
47-
}
48-
4974
// The `Vector` trait is provided in the prelude and is implemented on
5075
// both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
5176
// seamlessly. The other vector related traits from the prelude do
@@ -59,13 +84,49 @@ impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
5984
fn as_slice<'a>(&'a self) -> &'a [T] {
6085
match self {
6186
&Growable(ref v) => v.as_slice(),
87+
&FixedLen(ref v) => v.as_slice(),
6288
&Borrowed(ref v) => v.as_slice(),
6389
}
6490
}
6591
}
6692

6793
impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
6894
fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<T> {
95+
// If we are building from scratch, might as well build the
96+
// most flexible variant.
6997
Growable(FromIterator::from_iter(iterator))
7098
}
7199
}
100+
101+
impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
102+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103+
self.as_slice().fmt(f)
104+
}
105+
}
106+
107+
impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
108+
/// Returns a copy of `self`.
109+
fn to_owned(&self) -> ~[T] {
110+
self.as_slice().to_owned()
111+
}
112+
113+
/// Convert `self` into an owned slice, not making a copy if possible.
114+
fn into_owned(self) -> ~[T] {
115+
match self {
116+
Growable(v) => v.as_slice().to_owned(),
117+
FixedLen(v) => v,
118+
Borrowed(v) => v.to_owned(),
119+
}
120+
}
121+
}
122+
123+
impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
124+
/// Convert `self` into a growable `Vec`, not making a copy if possible.
125+
pub fn into_vec(self) -> Vec<T> {
126+
match self {
127+
Growable(v) => v,
128+
FixedLen(v) => Vec::from_slice(v.as_slice()),
129+
Borrowed(v) => Vec::from_slice(v),
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)