Browse Source

Separation of Shared & Data

My other crate https://git.red-green.com/david/shared was over-crowded
with both a Shared structure and Data.

This crate will serve as Data, and the other crate Shared.
david 4 months ago
parent
commit
2bbe3b358a
7 changed files with 982 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 71 0
      Cargo.lock
  3. 13 0
      Cargo.toml
  4. 25 0
      examples/collection_data_example.rs
  5. 42 0
      examples/data_example.rs
  6. 827 0
      src/data.rs
  7. 3 0
      src/lib.rs

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 71 - 0
Cargo.lock

@@ -0,0 +1,71 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "data"
+version = "0.1.0"
+dependencies = [
+ "serde",
+ "shared",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.215"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "shared"
+version = "0.1.3"
+source = "git+https://git.red-green.com/david/shared#09ff6040e0c332dc2cc3ef22890da1022d2d50aa"
+
+[[package]]
+name = "syn"
+version = "2.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

+ 13 - 0
Cargo.toml

@@ -0,0 +1,13 @@
+[package]
+name = "data"
+version = "0.1.0"
+edition = "2021"
+
+[features]
+shared = ["dep:shared"]
+serde = ["dep:serde"]
+cast_into = []
+
+[dependencies]
+serde = { version = "1.0.215", features = ["derive"], optional = true}
+shared = {version = "0.1.3", git = "https://git.red-green.com/david/shared", optional = true}

+ 25 - 0
examples/collection_data_example.rs

@@ -0,0 +1,25 @@
+use data::Data;
+use std::collections::HashMap;
+
+fn main() {
+    // Let's quickly populate a map
+    let mut map: HashMap<String, Data> = HashMap::from([
+        ("gravity".to_string(), Data::from(9.81_f32)),
+        ("life".to_string(), Data::from(42_i32)),
+        ("cat".to_string(), Data::from("meow".to_string())),
+    ]);
+    // Hmm... ok, looks good.
+    map.insert("direct_insert".to_string(), Data::Bool(true));
+    // Now to stuff it into a single thing...
+    let map: Data = Data::from(map);
+    // Poof! (Now as of v0.1.1 we can't directly insert or get out, as Vec and HashMap have different parameters)
+
+    // Ok let's pull it all back out
+    let m: Result<HashMap<String, Data>, ()> = map.clone().try_into();
+    if let Ok(m) = m {
+        println!("m is {:?}", m);
+    } else {
+        println!("{:?}", map);
+    }
+    // Notice: Even with `cast_into` feature, this type of try_into will fail on any other Data variant (Capt. Obvious: Well yeah, the others are primitives so we could cast them)
+}

+ 42 - 0
examples/data_example.rs

@@ -0,0 +1,42 @@
+use data::Data;
+
+// A example borrowing some Data
+fn something(d: &Data) {
+    // Because Data implements Display (It also implements Debug {:?})
+    println!("{}", d);
+}
+
+fn main() {
+    // Let's make a primitive
+    let my_uint: u32 = 42;
+    // Now notice the simplicity of converting from
+    let my_uint: Data = Data::from(my_uint);
+    let my_int: Data = Data::from(1024_i64);
+    let nothing: Data = Data::default(); // Want something empty?
+    
+    // Ok let's call something now
+    something(&my_uint);
+    something(&my_int);
+    something(&nothing);
+
+    // Directly? Sure!
+    println!("uint={} int={}", my_uint, my_int);
+
+    // Let's say we wanted to get it back out (by we know the original type)
+    let uint: Result<u32, ()> = my_uint.clone().try_into();
+    if let Ok(u) = uint {
+        println!("{:?}", u); // Yay, it is a u32
+    } else {
+        println!("{:?}", my_uint); // We had to clone it above so we can print it down here :)
+    }
+    // However, the above would fail if we try_into a different type (even something like u64 or u128 will "fail", despite the underlying being a u32)
+    // Don't want this? Use the `cast_into` feature (Then the u32 or lower will be casted to u64 or u128, but it only works lower bits to higher bits)
+
+    // We can get a general idea of what the type is, even a loose type like JSON's Number (which could be float or integer or even unsigned integer)
+    if my_int.is_number() {
+        println!("{} is a number", my_int);
+    }
+
+    // Data also supports being used in collections such as Vec<Data> and HashMap<String, Data>  (Note: HashMap will require String and Data, if the key is a number it's better to use a Vec)
+    // See collection_data_example.rs
+}

+ 827 - 0
src/data.rs

@@ -0,0 +1,827 @@
+use std::{collections::HashMap, fmt::Display, slice::{SliceIndex, Iter, IterMut}};
+
+#[cfg(feature = "shared")]
+use crate::Shared;
+
+#[cfg(not(feature = "serde"))]
+#[derive(Debug, PartialEq, Clone)]
+pub enum Data {
+    None,
+    String(String),
+    I8(i8),
+    I16(i16),
+    I32(i32),
+    I64(i64),
+    I128(i128),
+    U8(u8),
+    U16(u16),
+    U32(u32),
+    U64(u64),
+    U128(u128),
+    F32(f32),
+    F64(f64),
+    Bool(bool),
+    Vec(Vec<Data>),
+    Map(HashMap<String, Data>),
+}
+
+#[cfg(feature="serde")]
+#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
+pub enum Data {
+    None,
+    String(String),
+    I8(i8),
+    I16(i16),
+    I32(i32),
+    I64(i64),
+    I128(i128),
+    U8(u8),
+    U16(u16),
+    U32(u32),
+    U64(u64),
+    U128(u128),
+    F32(f32),
+    F64(f64),
+    Bool(bool),
+    Vec(Vec<Data>),
+    Map(HashMap<String, Data>),
+}
+
+impl Default for Data {
+    fn default() -> Self {
+        Self::None
+    }
+}
+
+impl Display for Data {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::None => f.write_str("None"),
+            Self::String(s) => f.write_str(s),
+            Self::I8(i) => f.write_str(format!("{}", i).as_str()),
+            Self::I16(i) => f.write_str(format!("{}", i).as_str()),
+            Self::I32(i) => f.write_str(format!("{}", i).as_str()),
+            Self::I64(i) => f.write_str(format!("{}", i).as_str()),
+            Self::I128(i) => f.write_str(format!("{}", i).as_str()),
+            Self::U8(i) => f.write_str(format!("{}", i).as_str()),
+            Self::U16(i) => f.write_str(format!("{}", i).as_str()),
+            Self::U32(i) => f.write_str(format!("{}", i).as_str()),
+            Self::U64(i) => f.write_str(format!("{}", i).as_str()),
+            Self::U128(i) => f.write_str(format!("{}", i).as_str()),
+            Self::F32(v) => f.write_str(format!("{}", v).as_str()),
+            Self::F64(v) => f.write_str(format!("{}", v).as_str()),
+            Self::Bool(b) => f.write_str(format!("{}", b).as_str()),
+            Self::Vec(v) => {
+                let mut out: String = "[".to_string();
+                for d in v.iter() {
+                    if out != "[" {
+                        out.push_str(", ");
+                    }
+                    out.push_str(format!("{}", d).as_str());
+                }
+                out.push(']');
+                f.write_str(out.as_str())
+            },
+            Self::Map(hm) => {
+                let mut out: String = "{".to_string();
+                for (k, v) in hm.iter() {
+                    if out != "{" {
+                        out.push_str(", ");
+                    }
+                    out.push_str(format!("{}: {}", k, v).as_str());
+                }
+                out.push('}');
+                f.write_str(out.as_str())
+            },
+        }
+    }
+}
+
+impl From<String> for Data {
+    fn from(value: String) -> Self {
+        Self::String(value)
+    }
+}
+
+impl From<i8> for Data {
+    fn from(value: i8) -> Self {
+        Self::I8(value)
+    }
+}
+
+impl From<i16> for Data {
+    fn from(value: i16) -> Self {
+        Self::I16(value)
+    }
+}
+
+impl From<i32> for Data {
+    fn from(value: i32) -> Self {
+        Self::I32(value)
+    }
+}
+
+impl From<i64> for Data {
+    fn from(value: i64) -> Self {
+        Self::I64(value)
+    }
+}
+
+impl From<i128> for Data {
+    fn from(value: i128) -> Self {
+        Self::I128(value)
+    }
+}
+
+impl From<u8> for Data {
+    fn from(value: u8) -> Self {
+        Self::U8(value)
+    }
+}
+
+impl From<u16> for Data {
+    fn from(value: u16) -> Self {
+        Self::U16(value)
+    }
+}
+
+impl From<u32> for Data {
+    fn from(value: u32) -> Self {
+        Self::U32(value)
+    }
+}
+
+impl From<u64> for Data {
+    fn from(value: u64) -> Self {
+        Self::U64(value)
+    }
+}
+
+impl From<u128> for Data {
+    fn from(value: u128) -> Self {
+        Self::U128(value)
+    }
+}
+
+impl From<f32> for Data {
+    fn from(value: f32) -> Self {
+        Self::F32(value)
+    }
+}
+
+impl From<f64> for Data {
+    fn from(value: f64) -> Self {
+        Self::F64(value)
+    }
+}
+
+impl From<bool> for Data {
+    fn from(value: bool) -> Self {
+        Self::Bool(value)
+    }
+}
+
+impl From<Vec<Data>> for Data {
+    fn from(value: Vec<Data>) -> Self {
+        Self::Vec(value)
+    }
+}
+
+impl From<HashMap<String, Data>> for Data {
+    fn from(value: HashMap<String, Data>) -> Self {
+        Self::Map(value)
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<String> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<String, Self::Error> {
+        match self {
+            Self::String(s) => Ok(s),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<String> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<String, Self::Error> {
+        Ok(format!("{}", self)) // Reuse Display trait
+    }
+}
+
+// i8 is the smallest bit variant... so no cast_into feature
+impl TryInto<i8> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i8, Self::Error> {
+        match self {
+            Self::I8(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<i16> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i16, Self::Error> {
+        match self {
+            Self::I16(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<i16> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i16, Self::Error> {
+        match self {
+            Self::I8(v) => Ok(v as i16), // bump up
+            Self::I16(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<i32> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i32, Self::Error> {
+        match self {
+            Self::I32(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<i32> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i32, Self::Error> {
+        match self {
+            Self::I8(v) => Ok(v as i32), // bump up
+            Self::I16(v) => Ok(v as i32), // bump up
+            Self::I32(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<i64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i64, Self::Error> {
+        match self {
+            Self::I64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<i64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i64, Self::Error> {
+        match self {
+            Self::I8(v) => Ok(v as i64), // bump up
+            Self::I16(v) => Ok(v as i64), // bump up
+            Self::I32(v) => Ok(v as i64), // bump up
+            Self::I64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<i128> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i128, Self::Error> {
+        match self {
+            Self::I128(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<i128> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<i128, Self::Error> {
+        match self {
+            Self::I8(v) => Ok(v as i128), // bump up
+            Self::I16(v) => Ok(v as i128), // bump up
+            Self::I32(v) => Ok(v as i128), // bump up
+            Self::I64(v) => Ok(v as i128), // bump up
+            Self::I128(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+// u8 is the smallest bit variant, so no cast_into
+impl TryInto<u8> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u8, Self::Error> {
+        match self {
+            Self::U8(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<u16> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u16, Self::Error> {
+        match self {
+            Self::U16(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<u16> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u16, Self::Error> {
+        match self {
+            Self::U8(v) => Ok(v as u16), // bump up
+            Self::U16(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<u32> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u32, Self::Error> {
+        match self {
+            Self::U32(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<u32> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u32, Self::Error> {
+        match self {
+            Self::U8(v) => Ok(v as u32), // bump up
+            Self::U16(v) => Ok(v as u32), // bump up
+            Self::U32(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<u64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u64, Self::Error> {
+        match self {
+            Self::U64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<u64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u64, Self::Error> {
+        match self {
+            Self::U8(v) => Ok(v as u64), // bump up
+            Self::U16(v) => Ok(v as u64), // bump up
+            Self::U32(v) => Ok(v as u64), // bump up
+            Self::U64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<u128> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u128, Self::Error> {
+        match self {
+            Self::U128(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<u128> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<u128, Self::Error> {
+        match self {
+            Self::U8(v) => Ok(v as u128), // bump up
+            Self::U16(v) => Ok(v as u128), // bump up
+            Self::U32(v) => Ok(v as u128), // bump up
+            Self::U64(v) => Ok(v as u128), // bump up
+            Self::U128(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+// because float only has 32 or 64, f32 will have no cast_into
+impl TryInto<f32> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<f32, Self::Error> {
+        match self {
+            Self::F32(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<f64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<f64, Self::Error> {
+        match self {
+            Self::F64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<f64> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<f64, Self::Error> {
+        match self {
+            Self::F32(v) => Ok(v as f64), // bump up
+            Self::F64(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(not(feature = "cast_into"))]
+impl TryInto<bool> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<bool, Self::Error> {
+        match self {
+            Self::Bool(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(feature = "cast_into")]
+impl TryInto<bool> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<bool, Self::Error> {
+        match self {
+            Self::String(s) => Ok(!s.is_empty()),
+            Self::I8(v) => Ok(v != 0),
+            Self::I16(v) => Ok(v != 0),
+            Self::I32(v) => Ok(v != 0),
+            Self::I64(v) => Ok(v != 0),
+            Self::I128(v) => Ok(v != 0),
+            Self::U8(v) => Ok(v != 0),
+            Self::U16(v) => Ok(v != 0),
+            Self::U32(v) => Ok(v != 0),
+            Self::U64(v) => Ok(v != 0),
+            Self::U128(v) => Ok(v != 0),
+            Self::F32(v) => Ok(v != 0.0),
+            Self::F64(v) => Ok(v != 0.0),
+            Self::Bool(b) => Ok(b),
+            _ => Err(()),
+        }
+    }
+}
+
+// cast_into doesn't make sense here
+impl TryInto<Vec<Data>> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<Vec<Data>, Self::Error> {
+        match self {
+            Self::Vec(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+// cast_into doesn't make sense here
+impl TryInto<HashMap<String, Data>> for Data {
+    type Error = ();
+    fn try_into(self) -> Result<HashMap<String, Data>, Self::Error> {
+        match self {
+            Self::Map(v) => Ok(v),
+            _ => Err(()),
+        }
+    }
+}
+
+
+// To cast Data into `Shared<Data>`
+// (Because we're still in the crate, we can do this)
+#[cfg(feature = "shared")]
+impl From<Data> for Shared<Data> {
+    fn from(v: Data) -> Self {
+        Shared::new(v)
+    }
+}
+
+impl Data {
+    /// Constructs a new empty Vec of `Vec<Data>`
+    pub fn new_vec() -> Self {
+        Self::Vec(Vec::new())
+    }
+    /// Constructs a new empty Map of `HashMap<String, Data>`
+    pub fn new_map() -> Self {
+        Self::Map(HashMap::new())
+    }
+    /// Constructs a new Vec with capacity
+    pub fn vec_with_capacity(cap: usize) -> Self {
+        Self::Vec(Vec::with_capacity(cap))
+    }
+    /// Constructs a new Map with capacity
+    pub fn map_with_capacity(cap: usize) -> Self {
+        Self::Map(HashMap::with_capacity(cap))
+    }
+    /// Is Data not the variant None
+    ///
+    /// This is useful for using Data similar to a Option
+    pub fn is_some(&self) -> bool {
+        !matches!(self, Self::None)
+    }
+    /// Is Data the variant None
+    pub fn is_none(&self) -> bool {
+        matches!(self, Self::None)
+    }
+    /// Is Data a String
+    pub fn is_string(&self) -> bool {
+        matches!(self, Self::String(_))
+    }
+    /// Is Data a signed/unsigned integer or float
+    ///
+    /// JSON Number's can hold both a whole number (i.e. signed/unsigned integers) and floats
+    pub fn is_number(&self) -> bool {
+        matches!(self, Self::I8(_) | Self::I16(_) | Self::I32(_) | Self::I64(_) | Self::I128(_) | Self::U8(_) | Self::U16(_) | Self::U32(_) | Self::U64(_) | Self::U128(_) | Self::F32(_) | Self::F64(_))
+    }
+    /// Is Data a signed integer (Regardless of bits)
+    ///
+    /// i.e. i8, i16, i32, i64, i128 or neither
+    pub fn is_int(&self) -> bool {
+        matches!(self, Self::I8(_) | Self::I16(_) | Self::I32(_) | Self::I64(_) | Self::I128(_))
+    }
+    /// Is Data a unsigned integer (Regardless of bits)
+    ///
+    /// i.e. u8, u16, u32, u64, or u128 or neither
+    pub fn is_uint(&self) -> bool {
+        matches!(self, Self::U8(_) | Self::U16(_) | Self::U32(_) | Self::U64(_) | Self::U128(_))
+    }
+    /// Is Data a f32 or f64 or neither
+    pub fn is_float(&self) -> bool {
+        matches!(self, Self::F32(_) | Self::F64(_))
+    }
+    /// Does Data contain something that holds other Data
+    ///
+    /// `Vec<Data>` or `HashMap<String, Data>` are examples of "nested" Data
+    pub fn is_nested(&self) -> bool {
+        matches!(self, Self::Vec(_) | Self::Map(_))
+    }
+    /// Is Data the Data::Vec variant (`Vec<Data>`)
+    pub fn is_vec(&self) -> bool {
+        matches!(self, Self::Vec(_))
+    }
+    /// Is Data the Data::Map variant (`HashMap<String, Data>`)
+    pub fn is_map(&self) -> bool {
+        matches!(self, Self::Map(_))
+    }
+    /// Push a value into the Data
+    ///
+    /// Must be a Vec or no-op
+    pub fn vec_push(&mut self, v: Data) {
+        if let Self::Vec(vec) = self {
+            vec.push(v);
+        }
+    }
+    /// Assigns/Reassigns a key the value into the Data
+    ///
+    /// Must be a Map or no-op
+    pub fn map_insert(&mut self, k: String, v: Data) {
+        if let Self::Map(hm) = self {
+            hm.insert(k, v);
+        }
+    }
+    /// Obtains the length of String, Vec or Map
+    ///
+    /// All other variants of Data will return 0
+    pub fn len(&self) -> usize {
+        match self {
+            Self::String(s) => s.len(),
+            Self::Vec(v) => v.len(),
+            Self::Map(m) => m.len(),
+            _ => 0,
+        }
+    }
+    /// Obtains the capacity of Vec or Map
+    ///
+    /// All other variants of Data return 0
+    pub fn capacity(&self) -> usize {
+        match self {
+            Self::Vec(v) => v.capacity(),
+            Self::Map(m) => m.capacity(),
+            _ => 0,
+        }
+    }
+    /// Reserve {additional} in a Vec or Map
+    ///
+    /// This no-op's if the Data variants are not Vec or Map
+    pub fn reserve(&mut self, additional: usize) {
+        match self {
+            Self::Vec(v) => v.reserve(additional),
+            Self::Map(m) => m.reserve(additional),
+            _ => (),
+        }
+    }
+    /// Shrinks a Vec or Map to fit all that is within it
+    pub fn shrink_to_fit(&mut self) {
+        match self {
+            Self::Vec(v) => v.shrink_to_fit(),
+            Self::Map(m) => m.shrink_to_fit(),
+            _ => (),
+        }
+    }
+    /// Shrinks to a given minimum length for Vec or Map
+    pub fn shrink_to(&mut self, min: usize) {
+        match self {
+            Self::Vec(v) => v.shrink_to(min),
+            Self::Map(m) => m.shrink_to(min),
+            _ => (),
+        }
+    }
+    /// Truncates Vec to a set length, see [Vec::truncate]
+    pub fn vec_truncate(&mut self, len: usize) {
+        if let Self::Vec(v) = self { v.truncate(len) }
+    }
+    /// Removes Vec at given index, see [Vec::remove]
+    pub fn vec_remove(&mut self, index: usize) -> Data {
+        match self {
+            Self::Vec(v) => v.remove(index),
+            _ => Data::None,
+        }
+    }
+    /// Removes the last item in the Vec, see [Vec::pop]
+    ///
+    /// This will return None also if the Data isn't a Vec
+    pub fn vec_pop(&mut self) -> Option<Data> {
+        match self {
+            Self::Vec(v) => v.pop(),
+            _ => None,
+        }
+    }
+    /// Clears all in a String, Vec or Map
+    pub fn clear(&mut self) {
+        match self {
+            Self::String(s) => s.clear(),
+            Self::Vec(v) => v.clear(),
+            Self::Map(m) => m.clear(),
+            _ => (),
+        }
+    }
+    /// Returns if String, Vec or Map is empty (has no elements)
+    pub fn is_empty(&self) -> bool {
+        match self {
+            Self::String(s) => s.is_empty(),
+            Self::Vec(v) => v.is_empty(),
+            Self::Map(m) => m.is_empty(),
+            _ => false,
+        }
+    }
+    /// Resizes the Vec with the given length, assigning new with value
+    pub fn vec_resize(&mut self, len: usize, value: Data) {
+        if let Self::Vec(v) = self { v.resize(len, value) }
+    }
+    /// Obtains the first element in Vec
+    pub fn vec_first(&self) -> Option<&Data> {
+        match self {
+            Self::Vec(v) => v.first(),
+            _ => None,
+        }
+    }
+    /// Similar to [Data::vec_first] except it obtains as mutable
+    pub fn vec_first_mut(&mut self) -> Option<&mut Data> {
+        match self {
+            Self::Vec(v) => v.first_mut(),
+            _ => None,
+        }
+    }
+    /// Similar to [Data::vec_first] except obtains the last element of Vec
+    pub fn vec_last(&self) -> Option<&Data> {
+        match self {
+            Self::Vec(v) => v.last(),
+            _ => None,
+        }
+    }
+    /// Similar to [Data::vec_last] except obtains as mutable
+    pub fn vec_last_mut(&mut self) -> Option<&mut Data> {
+        match self {
+            Self::Vec(v) => v.last_mut(),
+            _ => None,
+        }
+    }
+    /// Gets by index or range for a Vec
+    pub fn vec_get<I>(&self, index: I) -> Option<&I::Output>
+    where
+        I: SliceIndex<[Data]>,
+    {
+        match self {
+            Self::Vec(v) => v.get::<I>(index),
+            _ => None,
+        }
+    }
+    /// Gets like [Data::vec_get] except as mutable
+    pub fn vec_get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
+    where
+        I: SliceIndex<[Data]>,
+    {
+        match self {
+            Self::Vec(v) => v.get_mut::<I>(index),
+            _ => None,
+        }
+    }
+    pub fn map_contains_key(&self, key: &String) -> bool {
+        match self {
+            Self::Map(hm) => hm.contains_key(key),
+            _ => false,
+        }
+    }
+    /// Get for a Map, see [HashMap::get]
+    pub fn map_get(&self, key: &String) -> Option<&Data> {
+        match self {
+            Self::Map(hm) => hm.get(key),
+            _ => None
+        }
+    }
+    /// Get as mutable for a Map
+    pub fn map_get_mut(&mut self, key: &String) -> Option<&mut Data> {
+        match self {
+            Self::Map(hm) => hm.get_mut(key),
+            _ => None
+        }
+    }
+    /// Get Key & Value for a Map
+    pub fn map_get_key_value(&self, key: &String) -> Option<(&String, &Data)> {
+        match self {
+            Self::Map(hm) => hm.get_key_value(key),
+            _ => None
+        }
+    }
+    /// Removes for a Map
+    pub fn map_remove(&mut self, key: &String) -> Option<Data> {
+        match self {
+            Self::Map(hm) => hm.remove(key),
+            _ => None
+        }
+    }
+    /// Swaps a with b in a Vec
+    pub fn vec_swap(&mut self, a: usize, b: usize) {
+        if let Self::Vec(v) = self { v.swap(a, b) }
+    }
+    /// Reverses the order of a Vec
+    pub fn vec_reverse(&mut self) {
+        if let Self::Vec(v) = self { v.reverse() }
+    }
+    /// Attempts to form an iterator for Vec
+    ///
+    /// This can fail if Data isn't a Vec
+    pub fn vec_iter(&self) -> Option<Iter<'_, Data>> {
+        match self {
+            Self::Vec(v) => Some(v.iter()),
+            _ => None,
+        }
+    }
+    /// Attempts to form a mutable iterator for Vec
+    ///
+    /// This can fail if Data isn't a Vec
+    pub fn vec_iter_mut(&mut self) -> Option<IterMut<'_, Data>> {
+        match self {
+            Self::Vec(v) => Some(v.iter_mut()),
+            _ => None,
+        }
+    }
+    /// This will determine the size of signed or unsigned integers and floats
+    ///
+    /// i.e. i32 is 32, u64 is 64, f32 is 32, u128 is 128 (Meanwhile, anything else is 0, String is 0, Bool is 0, etc.)
+    pub fn bit_variant(&self) -> u8 {
+        match self {
+            Self::I8(_) | Self::U8(_) => 8,
+            Self::I16(_) | Self::U16(_) => 16,
+            Self::I32(_) | Self::U32(_) | Self::F32(_) => 32,
+            Self::I64(_) | Self::U64(_) | Self::F64(_) => 64,
+            Self::I128(_) | Self::U128(_) => 128,
+            _ => 0
+        }
+    }
+}

+ 3 - 0
src/lib.rs

@@ -0,0 +1,3 @@
+
+mod data;
+pub use crate::data::Data;