clippet/
lib.rs

1//! Provides a teeny way to have some nice byte structures that's easy to use.
2//! It's all provided in one structure and many function implementation.
3use bytes::BytesMut;
4use std::io::BufReader;
5use std::io::prelude::*;
6use std::fs::File;
7
8/// A structure for containing chunks of data and information about it.
9/// The label field is useful for storing things like MIME types.
10/// The size field is automatically increased when you append to the data field.
11#[derive(Debug)]
12pub struct Clippet {
13	label: String,
14	size: i32,
15	data: Vec<BytesMut>,
16}
17
18impl Clippet {
19	/// Returns the label field.
20	///
21	/// ```no_run
22	/// let data = Clippet { label : "Hello!".to_string(), ... };
23	/// assert_eq!(data.get_label(), "Hello!")
24	/// ```
25	pub fn get_label(&self) -> String {
26		return self.label.to_string()
27	}
28	/// Changes the label field.
29	///
30	/// ```no_run
31	/// let data = Clippet { ... };
32	/// assert_eq!(data.set_label("Hello!"), true);
33	/// ```
34	pub fn set_label(&mut self, label: &str) -> bool {
35		self.label = label.to_string();
36		if &self.label == label {
37			return true
38		} else {
39			return false
40		}
41	}
42	/// Appends a sequence of bytes to the Clippet structure.
43	/// Also increases the size field by one.
44	///
45	/// ```no_run
46	/// let bytes = BytesMut::from("Hello, world!");
47	/// let mut data = Clippet { ... };
48	/// data.add_bytes(bytes);
49	/// ```
50	pub fn add_bytes(&mut self, bytes: BytesMut) {
51		self.data.push(bytes);
52		self.size = self.size + 1;
53	}
54	/// Removes a sequence of bytes from the Clippet structure.
55	/// Also decreases the size field by one.
56	///
57	/// ```no_run
58	/// let mut data = Clippet { ... };
59	/// data.get_size() // e.g. 10
60	/// data.drop_bytes(5) // drops 6th sequence of bytes
61	/// data.get_size() // 9
62	/// ```
63	pub fn drop_bytes(&mut self, index: usize) {
64		self.data.remove(index);
65		self.size = self.size - 1;
66	}
67	/// Returns the size of the data field.
68	///
69	/// ```no_run
70	/// let data = Clippet { ... };
71	/// assert_eq!(data.get_size(), 0);
72	/// ```
73	pub fn get_size(&self) -> i32 {
74		return self.size
75	}
76	/// Returns a sequence of bytes.
77	///
78	/// ```no_run
79	/// let bytes = BytesMut::from("Hello, world!");
80	/// let mut data = Clippet { ... };
81	/// data.add_bytes(bytes);
82	/// assert_eq!(data.get_data(0), bytes);
83	/// ```
84	pub fn get_data(&self, index: usize) -> BytesMut {
85		return self.data[index].to_owned()
86	}
87	/// Takes an indexed byte sequence and returns it as a String.
88	/// ```no_run
89	/// let bytes = BytesMut::from("Hello, world!");
90	/// let mut data = Clippet { ... };
91	/// data.add_bytes(bytes);
92	/// assert_eq!(data.get_as_string(0), "Hello, world!");
93	/// ```
94	pub fn get_as_string(&self, index: usize) -> String {
95		let bytes = self.get_data(index);
96		let y = bytes.as_ref();
97		let x = String::from_utf8_lossy(y).to_string();
98		return x
99	}
100	/// Takes a filename and splits it into sequences of bytes within a Clippet.
101	/// It is recommended to use smaller byte sequences, however this is user-configurable.
102	///
103	/// ```no_run
104	/// let data = Clippet::from_file("example.txt", 512);
105	/// ```
106	pub fn from_file(name: &str, size: usize) -> Clippet {
107		let mut i = false;
108		let mut data: Vec<BytesMut> = vec![];
109		let f = File::open(name).unwrap();
110		let mut reader = BufReader::with_capacity(size, f);
111		while !i {
112			let buffer = reader.fill_buf().unwrap();
113			let bytes = BytesMut::from(buffer);
114			data.push(bytes);
115			let length = buffer.len();
116			if length < size { i = true; }
117			reader.consume(length);
118		}
119		let clip = Clippet { label: "".to_string(), size: data.len() as i32, data: data };
120		return clip
121		
122	}
123	/// Takes a sequence of bytes and wraps it around a Clippet structure.
124	///
125	/// ```no_run
126	/// let data = Clippet::from_bytes(foo);
127	/// ```
128	pub fn from_bytes(bytes: BytesMut) -> Clippet {
129		let clip = Clippet { label: "".to_string(), size: 1, data: vec![bytes] };
130		return clip
131	}
132	/// Alias of `get_size(&self)`
133	pub fn len(&self) -> i32 {
134		return self.get_size()
135	}
136	/// Takes a string and splits it into sequences of bytes within a Clippet.
137	/// It is recommended to use smaller byte sequences, however this is user-configurable.
138	/// This uses a string reference.
139	///
140	/// ```no_run
141	/// let data = Clippet::from_string("Lorem ipsum dolor amet...", 512);
142	/// ```
143	pub fn from_string(str: &str, size: usize) -> Clippet {
144		let mut i = false;
145		let mut data: Vec<BytesMut> = vec![];
146		let string = str.as_bytes();
147		let mut reader = BufReader::with_capacity(size, string);
148		while !i {
149			let buffer = reader.fill_buf().unwrap();
150			let bytes = BytesMut::from(buffer);
151			data.push(bytes);
152			let length = buffer.len();
153			if length < size { i = true; }
154			reader.consume(length);
155		}
156		let clip = Clippet { label: "".to_string(), size: data.len() as i32, data: data };
157		return clip
158		
159	}
160	/// Consumes the Clippet, combines all of its byte sequences and outputs them as a String literal.
161	///
162	/// ```no_run
163	/// let data = Clippet::from_string("Hello, World!", 512);
164	/// println!("{}", data.combine()); /// Hello, World!
165	/// ```
166	pub fn combine(self) -> String {
167		let mut string = "".to_string();
168		for v in self.data {
169			let y = v.as_ref();
170			let x = String::from_utf8_lossy(y).to_string();
171			if string == "".to_string() {
172				string = x;
173			} else {
174				string = format!("{}{}", string, x);
175			}
176		}
177		return string
178	}
179	/// Replaces the Clippet with one that has all of its data in one chunk.
180	/// The label is retained, the data is not modified apart from being dechunked.
181	///
182	/// ```no_run
183	/// let data = Clippet::from_string("HelloWorld", 5); // [b"Hello", b"World"]
184	/// let data = data.dechunk(); // [b"HelloWorld"]
185	/// ```
186	pub fn dechunk(self) -> Clippet {
187		// Retain label.
188		let label = self.label.to_string();
189		let data = self.combine();
190		let clip = Clippet { label: label, size: 1, data: vec![BytesMut::from(data.as_str())] };
191		return clip
192	}
193	/// Combines the Clippet and then remakes it, retaining the label, with the specified max chunk size.
194	/// No data is modified.
195	///
196	/// ```no_run
197	/// let longstring = "long string bla bla bla..."; // Pretend this is 2KB large!
198	/// let data = Clippet::from_string(longstring, 512); // size: 4
199	/// let data = data.rechunk(1024) // size: 2
200	/// ```
201	pub fn rechunk(self, size: usize) -> Clippet {
202		let label = self.label.to_string();
203		let data = self.combine();
204		let mut clip = Clippet::from_string(&data, size);
205		if label != "".to_string() { clip.label = label; }
206		return clip
207	}
208}