diff --git a/Cargo.toml b/Cargo.toml index 0736ad2..95ec793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bigbit" -version = "0.0.6" +version = "0.0.7" authors = ["Kotauskas "] edition = "2018" description = "Implements the BigBig format, allowing for compact storage of arbitrarily large numbers." diff --git a/README.md b/README.md index 723b5f0..8da7dba 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ And here's a list of what's not finished just yet: - **Tests** (planned for 0.1.0 but might be partially added earlier) ## Changelog +### 0.0.7 +- Implemented some traits for `LBString`s, allowing for quick conversion to and from `String`s +### 0.0.6 +- Added `LBString`, which is an owned string type implementing the Linked Bytes Unicode encoding, allowing for efficient storage of Unicode strings which is under all circumstances more compact than all current UTF encodings +- Added `LBNumRef` addition, which was missing due to a copypasting mistake ### 0.0.5 - Implemented arithmetic with `self` as the right operand for Linked Bytes, removing the need to always explicitly write `op1 + &op2` (same for other operators) - Fixed the Crates.io badge to link to `bigbit` instead of `bi`**`t`**`bit` diff --git a/src/lib.rs b/src/lib.rs index ebaae9f..a0cbc91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,8 @@ //! - **Tests** (planned for 0.1.0 but might be partially added earlier) //! //! # Changelog +//! ## 0.0.7 +//! - Implemented some traits for `LBString`s, allowing for quick conversion to and from `String`s //! ## 0.0.6 //! - Added `LBString`, which is an owned string type implementing the Linked Bytes Unicode encoding, allowing for efficient storage of Unicode strings which is under all circumstances more compact than all current UTF encodings //! - Added `LBNumRef` addition, which was missing due to a copypasting mistake diff --git a/src/linkedbytes.rs b/src/linkedbytes.rs index 3f09c49..55ce5c1 100644 --- a/src/linkedbytes.rs +++ b/src/linkedbytes.rs @@ -2,8 +2,8 @@ //! //! If you only want non-negative integers, you should stick to this format. (Signed LB integers are also planned.) Otherwise, use either Head Byte or Extended Head Byte. -use core::slice::SliceIndex; -use alloc::{vec::Vec, string::String}; +use core::{slice::SliceIndex, cmp::Ordering}; +use alloc::vec::Vec; /// The `Result` specialization for the methods converting iterators/arrays of bytes into instances of `LBNum`. pub type DecodeResult = Result; @@ -318,6 +318,18 @@ impl LBString { LBCharsIter::new(self) } + /// Counts the number of **codepoints** stored. + /// + /// This will iterate through the entire string and count how many codepoints were resolved successfully. Currently, this is implemented as simply `self.chars().count()`. + #[inline(always)] + pub fn len(&self) -> usize { + self.chars().count() + } + /// Returns `true` if there are no codepoints stored, `false` otherwise. + #[inline(always)] + pub fn is_empty(&self) -> bool { + self.0.is_empty() // We can use the container length, since if it's 0, then it's pointless to try to iterate, otherwise there's guaranteed to be a codepoint. + } /// Returns an immutable reference to the underlying sequence. #[inline(always)] pub fn inner(&self) -> &LBSequence { @@ -344,30 +356,6 @@ impl<'a> core::iter::FromIterator<&'a char> for LBString { iter.into_iter().copied().collect::() } } -impl From<&String> for LBString { - #[inline(always)] - fn from(op: &String) -> Self { - op.chars().collect::() - } -} -impl From for LBString { - #[inline(always)] - fn from(op: String) -> Self { - op.chars().collect::() - } -} -impl<'a> From<&'a str> for LBString { - #[inline(always)] - fn from(op: &'a str) -> Self { - op.chars().collect::() - } -} -impl From for String { - #[inline(always)] - fn from(op: LBString) -> Self { - op.chars().collect::() - } -} impl core::fmt::Display for LBString { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { use core::fmt::Write; @@ -731,15 +719,13 @@ impl core::fmt::Debug for LinkedByte { ds.finish() } } - -use core::cmp::{self, Ordering}; -impl cmp::PartialOrd for LinkedByte { +impl PartialOrd for LinkedByte { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl cmp::Ord for LinkedByte { +impl Ord for LinkedByte { #[inline(always)] fn cmp(&self, other: &Self) -> Ordering { self.into_end().0.cmp(&other.into_end().0) diff --git a/src/ops/lbstring/cmp.rs b/src/ops/lbstring/cmp.rs new file mode 100644 index 0000000..46fd401 --- /dev/null +++ b/src/ops/lbstring/cmp.rs @@ -0,0 +1,81 @@ +use crate::LBString; +use alloc::string::String; +use core::cmp::Ordering; // We're not gonna deal with atomics here, right? + +impl PartialEq for LBString { + #[inline(always)] + fn eq(&self, rhs: &Self) -> bool { + self.cmp(rhs) == Ordering::Equal + } +} +impl Eq for LBString {} +impl PartialOrd for LBString { + #[inline(always)] + fn partial_cmp(&self, rhs: &Self) -> Option { + Some(self.cmp(rhs)) + } +} +impl Ord for LBString { + #[inline] + fn cmp(&self, rhs: &Self) -> Ordering { + let (mut chars_l, mut chars_r) = (self.chars(), rhs.chars()); + loop { + let (l, r) = (chars_l.next(), chars_r.next()); + if let Some(l_val) = l { + if let Some(r_val) = r { + match l_val.cmp(&r_val) { + Ordering::Greater => {return Ordering::Greater;}, + Ordering::Less => {return Ordering::Less;}, + Ordering::Equal => {} + } + } else {return Ordering::Greater;} + } else if r.is_some() {return Ordering::Less;} else {break;} + } + Ordering::Equal + } +} + +macro_rules! impl_pcmp_for_chars { + ($ty:ident) => { + impl PartialEq<$ty> for LBString { + #[inline(always)] + fn eq(&self, rhs: &$ty) -> bool { + self.partial_cmp(rhs) == Some(Ordering::Equal) + } + } + impl PartialOrd<$ty> for LBString { + fn partial_cmp(&self, rhs: &$ty) -> Option { + let (mut chars_l, mut chars_r) = (self.chars(), rhs.chars()); + loop { + let (l, r) = (chars_l.next(), chars_r.next()); + if let Some(l_val) = l { + if let Some(r_val) = r { + match l_val.cmp(&r_val) { + Ordering::Greater => {return Some(Ordering::Greater);}, + Ordering::Less => {return Some(Ordering::Less);}, + Ordering::Equal => {} + } + } else {return Some(Ordering::Greater);} + } else if r.is_some() {return Some(Ordering::Less);} else {break;} + } + Some(Ordering::Equal) + } + } + + impl PartialEq for $ty { + #[inline(always)] + fn eq(&self, rhs: &LBString) -> bool { + self.partial_cmp(rhs) == Some(Ordering::Equal) + } + } + impl PartialOrd for $ty { + #[inline(always)] + fn partial_cmp(&self, rhs: &LBString) -> Option { + rhs.partial_cmp(self) + } + } + }; +} + +impl_pcmp_for_chars!(String); +impl_pcmp_for_chars!(str); \ No newline at end of file diff --git a/src/ops/lbstring/from.rs b/src/ops/lbstring/from.rs new file mode 100644 index 0000000..d9e4c52 --- /dev/null +++ b/src/ops/lbstring/from.rs @@ -0,0 +1,21 @@ +use alloc::string::String; +use crate::LBString; + +impl From<&String> for LBString { + #[inline(always)] + fn from(op: &String) -> Self { + op.chars().collect::() + } +} +impl From for LBString { + #[inline(always)] + fn from(op: String) -> Self { + op.chars().collect::() + } +} +impl<'a> From<&'a str> for LBString { + #[inline(always)] + fn from(op: &'a str) -> Self { + op.chars().collect::() + } +} \ No newline at end of file diff --git a/src/ops/lbstring/into.rs b/src/ops/lbstring/into.rs new file mode 100644 index 0000000..1161d3d --- /dev/null +++ b/src/ops/lbstring/into.rs @@ -0,0 +1,9 @@ +use alloc::string::String; +use crate::LBString; + +impl From for String { + #[inline(always)] + fn from(op: LBString) -> Self { + op.chars().collect::() + } +} \ No newline at end of file diff --git a/src/ops/lbstring/mod.rs b/src/ops/lbstring/mod.rs new file mode 100644 index 0000000..33a6adc --- /dev/null +++ b/src/ops/lbstring/mod.rs @@ -0,0 +1,3 @@ +mod from; mod into; mod cmp; +#[allow(unused_imports)] +pub(crate) use {from::*, into::*, cmp::*}; \ No newline at end of file diff --git a/src/ops/mod.rs b/src/ops/mod.rs index cb94991..3978c77 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -1,4 +1,5 @@ -// Uncomment when implementing arithmetics for these +// Uncomment when implementing operations for these //pub(crate) mod headbyte; //pub(crate) mod extheadbyte; -pub(crate) mod linkedbytes; \ No newline at end of file +pub(crate) mod linkedbytes; +pub(crate) mod lbstring; \ No newline at end of file