about summary refs log tree commit diff
path: root/src/libsyntax/util
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2018-08-12 12:45:48 -0700
committerDavid Tolnay <dtolnay@gmail.com>2018-08-12 22:45:32 -0700
commit2fa1da991945b2c2d3b36241492f7e8280869fd0 (patch)
tree227a54b4bc56f4e20e3b846e721d881a9093a824 /src/libsyntax/util
parent0aa8d0320266b5579428312095fe49af05ada972 (diff)
downloadrust-2fa1da991945b2c2d3b36241492f7e8280869fd0.tar.gz
rust-2fa1da991945b2c2d3b36241492f7e8280869fd0.zip
TokenStream::extend
Diffstat (limited to 'src/libsyntax/util')
-rw-r--r--src/libsyntax/util/rc_vec.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs
new file mode 100644
index 00000000000..b2785d7143d
--- /dev/null
+++ b/src/libsyntax/util/rc_vec.rs
@@ -0,0 +1,95 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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 std::fmt;
+use std::ops::{Deref, Range};
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_data_structures::sync::Lrc;
+
+#[derive(Clone)]
+pub struct RcVec<T> {
+    data: Lrc<Vec<T>>,
+    offset: u32,
+    len: u32,
+}
+
+impl<T> RcVec<T> {
+    pub fn new(mut vec: Vec<T>) -> Self {
+        // By default, constructing RcVec from Vec gives it just enough capacity
+        // to hold the initial elements. Callers that anticipate needing to
+        // extend the vector may prefer RcVec::new_preserving_capacity.
+        vec.shrink_to_fit();
+
+        RcVec {
+            offset: 0,
+            len: vec.len() as u32,
+            data: Lrc::new(vec),
+        }
+    }
+
+    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
+        RcVec {
+            offset: 0,
+            len: vec.len() as u32,
+            data: Lrc::new(vec),
+        }
+    }
+
+    pub fn sub_slice(&self, range: Range<usize>) -> Self {
+        RcVec {
+            data: self.data.clone(),
+            offset: self.offset + range.start as u32,
+            len: (range.end - range.start) as u32,
+        }
+    }
+
+    /// If this RcVec has exactly one strong reference, returns ownership of the
+    /// underlying vector. Otherwise returns self unmodified.
+    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
+        match Lrc::try_unwrap(self.data) {
+            // If no other RcVec shares ownership of this data.
+            Ok(mut vec) => {
+                // Drop any elements after our view of the data.
+                vec.truncate(self.offset as usize + self.len as usize);
+                // Drop any elements before our view of the data.
+                if self.offset != 0 {
+                    vec.drain(..self.offset as usize);
+                }
+                Ok(vec)
+            }
+
+            // If the data is shared.
+            Err(data) => Err(RcVec { data, ..self }),
+        }
+    }
+}
+
+impl<T> Deref for RcVec<T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        &self.data[self.offset as usize..(self.offset + self.len) as usize]
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.deref(), f)
+    }
+}
+
+impl<CTX, T> HashStable<CTX> for RcVec<T>
+where
+    T: HashStable<CTX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
+        (**self).hash_stable(hcx, hasher);
+    }
+}