use std::cmp::Ordering;
use std::fmt::Formatter;
use std::ops::{Deref, DerefMut};
use crate::symbol::iter_symbols;
use crate::{AmbiAmino, Seq, iter::display, packed::packable_array::ArrayDefault};
use super::peptide::{PackedArrayPeptide, PackedPeptide};
use super::{PackableArray, RefCmp};
#[derive(Clone, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PackedAmbiPeptide(Vec<[u8; 3]>);
impl PackedAmbiPeptide {
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn push(&mut self, ambi_amino: AmbiAmino) {
assert_ne!(self.len(), isize::MAX as usize / 4);
self.0.push(ambi_amino.compress());
}
pub fn pop(&mut self) -> Option<AmbiAmino> {
self.0.pop().map(AmbiAmino::decompress)
}
#[must_use]
pub fn iter(&self) -> PackedAmbiPeptideIter<'_> {
self.into_iter()
}
#[must_use]
pub fn iter_mut(&mut self) -> PackedAmbiPeptideMutIter<'_> {
self.into_iter()
}
}
impl From<Seq<Vec<AmbiAmino>>> for PackedAmbiPeptide {
fn from(ambi_peptide: Seq<Vec<AmbiAmino>>) -> PackedAmbiPeptide {
ambi_peptide.0.into()
}
}
impl From<Vec<AmbiAmino>> for PackedAmbiPeptide {
fn from(ambi_peptide: Vec<AmbiAmino>) -> PackedAmbiPeptide {
(&ambi_peptide).into()
}
}
impl<T: AsRef<[AmbiAmino]> + ?Sized> From<&T> for PackedAmbiPeptide {
fn from(ambi_peptide: &T) -> PackedAmbiPeptide {
let ambi_peptide = ambi_peptide.as_ref();
Self(ambi_peptide.iter().map(|a| a.compress()).collect())
}
}
impl From<PackedAmbiPeptide> for Seq<Vec<AmbiAmino>> {
fn from(packed_ambi_peptide: PackedAmbiPeptide) -> Seq<Vec<AmbiAmino>> {
Seq(packed_ambi_peptide.into())
}
}
impl From<&PackedAmbiPeptide> for Seq<Vec<AmbiAmino>> {
fn from(packed_ambi_peptide: &PackedAmbiPeptide) -> Seq<Vec<AmbiAmino>> {
Seq(packed_ambi_peptide.into())
}
}
impl From<PackedAmbiPeptide> for Vec<AmbiAmino> {
fn from(packed_ambi_peptide: PackedAmbiPeptide) -> Vec<AmbiAmino> {
(&packed_ambi_peptide).into()
}
}
impl From<&PackedAmbiPeptide> for Vec<AmbiAmino> {
fn from(packed_ambi_peptide: &PackedAmbiPeptide) -> Vec<AmbiAmino> {
let packed = packed_ambi_peptide.0.iter();
packed.map(|&bits| AmbiAmino::decompress(bits)).collect()
}
}
impl<'a> IntoIterator for &'a PackedAmbiPeptide {
type Item = AmbiAmino;
type IntoIter = PackedAmbiPeptideIter<'a>;
fn into_iter(self) -> Self::IntoIter {
PackedAmbiPeptideIter(self.0.iter())
}
}
impl<'a> IntoIterator for &'a mut PackedAmbiPeptide {
type Item = PackedAmbiAmino<'a>;
type IntoIter = PackedAmbiPeptideMutIter<'a>;
fn into_iter(self) -> Self::IntoIter {
PackedAmbiPeptideMutIter(self.0.iter_mut())
}
}
impl IntoIterator for PackedAmbiPeptide {
type Item = AmbiAmino;
type IntoIter = PackedAmbiPeptideIntoIter;
fn into_iter(self) -> Self::IntoIter {
PackedAmbiPeptideIntoIter(self.0.into_iter())
}
}
impl<const N: usize> PartialEq<PackedArrayAmbiPeptide<N>> for PackedAmbiPeptide {
fn eq(&self, other: &PackedArrayAmbiPeptide<N>) -> bool {
self.0.as_flattened().eq(other.0.as_ref().as_flattened())
}
}
impl<const N: usize> PartialOrd<PackedArrayAmbiPeptide<N>> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &PackedArrayAmbiPeptide<N>) -> Option<Ordering> {
self.0
.as_flattened()
.partial_cmp(other.0.as_ref().as_flattened())
}
}
impl PartialEq<PackedPeptide> for PackedAmbiPeptide {
fn eq(&self, other: &PackedPeptide) -> bool {
other == self
}
}
impl PartialOrd<PackedPeptide> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &PackedPeptide) -> Option<Ordering> {
other.partial_cmp(self).map(Ordering::reverse)
}
}
impl<const N: usize> PartialEq<PackedArrayPeptide<N>> for PackedAmbiPeptide
where
[(); N]: PackableArray,
{
fn eq(&self, other: &PackedArrayPeptide<N>) -> bool {
other == self
}
}
impl<const N: usize> PartialOrd<PackedArrayPeptide<N>> for PackedAmbiPeptide
where
[(); N]: PackableArray,
{
fn partial_cmp(&self, other: &PackedArrayPeptide<N>) -> Option<Ordering> {
other.partial_cmp(self).map(Ordering::reverse)
}
}
impl<T: PartialEq<AmbiAmino>, const M: usize> PartialEq<[T; M]> for PackedAmbiPeptide {
fn eq(&self, other: &[T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const M: usize> PartialOrd<[T; M]> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &[T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>, const M: usize> PartialEq<&mut [T; M]> for PackedAmbiPeptide {
fn eq(&self, other: &&mut [T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const M: usize> PartialOrd<&mut [T; M]> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &&mut [T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>, const M: usize> PartialEq<&[T; M]> for PackedAmbiPeptide {
fn eq(&self, other: &&[T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const M: usize> PartialOrd<&[T; M]> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &&[T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>> PartialEq<Vec<T>> for PackedAmbiPeptide {
fn eq(&self, other: &Vec<T>) -> bool {
self.eq(&&**other)
}
}
impl<T: PartialOrd<AmbiAmino>> PartialOrd<Vec<T>> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
self.partial_cmp(&&**other)
}
}
impl<T: PartialEq<AmbiAmino>> PartialEq<&mut [T]> for PackedAmbiPeptide {
fn eq(&self, other: &&mut [T]) -> bool {
self.eq(&&**other)
}
}
impl<T: PartialOrd<AmbiAmino>> PartialOrd<&mut [T]> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &&mut [T]) -> Option<Ordering> {
self.partial_cmp(&&**other)
}
}
impl<T: PartialEq<AmbiAmino>> PartialEq<&[T]> for PackedAmbiPeptide {
fn eq(&self, other: &&[T]) -> bool {
self.len() == other.len() && self.iter().map(RefCmp).eq(*other)
}
}
impl<T: PartialOrd<AmbiAmino>> PartialOrd<&[T]> for PackedAmbiPeptide {
fn partial_cmp(&self, other: &&[T]) -> Option<Ordering> {
self.iter().map(RefCmp).partial_cmp(*other)
}
}
impl PartialEq<&str> for PackedAmbiPeptide {
fn eq(&self, rhs: &&str) -> bool {
self == *rhs
}
}
impl PartialEq<str> for PackedAmbiPeptide {
fn eq(&self, rhs: &str) -> bool {
self.iter().map(Ok).eq(iter_symbols(rhs))
}
}
impl std::fmt::Display for PackedAmbiPeptide {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
self.iter().fmt(f)
}
}
impl std::fmt::Debug for PackedAmbiPeptide {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedAmbiPeptide")
.field(&display(self.iter()))
.finish()
}
}
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PackedArrayAmbiPeptide<const N: usize>([[u8; 3]; N]);
impl<const N: usize> PackedArrayAmbiPeptide<N> {
#[must_use]
pub fn iter(&self) -> PackedAmbiPeptideIter<'_> {
self.into_iter()
}
#[must_use]
pub fn iter_mut(&mut self) -> PackedAmbiPeptideMutIter<'_> {
self.into_iter()
}
}
impl<const N: usize> Default for PackedArrayAmbiPeptide<N> {
fn default() -> Self {
Self(ArrayDefault::array_default())
}
}
impl<const N: usize> From<Seq<[AmbiAmino; N]>> for PackedArrayAmbiPeptide<N> {
fn from(ambi_peptide: Seq<[AmbiAmino; N]>) -> PackedArrayAmbiPeptide<N> {
ambi_peptide.0.into()
}
}
impl<const N: usize> From<&Seq<[AmbiAmino; N]>> for PackedArrayAmbiPeptide<N> {
fn from(ambi_peptide: &Seq<[AmbiAmino; N]>) -> PackedArrayAmbiPeptide<N> {
ambi_peptide.0.into()
}
}
impl<const N: usize> From<[AmbiAmino; N]> for PackedArrayAmbiPeptide<N> {
fn from(ambi_peptide: [AmbiAmino; N]) -> PackedArrayAmbiPeptide<N> {
(&ambi_peptide).into()
}
}
impl<const N: usize> From<&[AmbiAmino; N]> for PackedArrayAmbiPeptide<N> {
fn from(ambi_peptide: &[AmbiAmino; N]) -> PackedArrayAmbiPeptide<N> {
Self(ambi_peptide.map(AmbiAmino::compress))
}
}
impl<const N: usize> From<PackedArrayAmbiPeptide<N>> for Seq<[AmbiAmino; N]> {
fn from(packed_ambi_peptide: PackedArrayAmbiPeptide<N>) -> Seq<[AmbiAmino; N]> {
Seq(packed_ambi_peptide.into())
}
}
impl<const N: usize> From<&PackedArrayAmbiPeptide<N>> for Seq<[AmbiAmino; N]> {
fn from(packed_ambi_peptide: &PackedArrayAmbiPeptide<N>) -> Seq<[AmbiAmino; N]> {
Seq(packed_ambi_peptide.into())
}
}
impl<const N: usize> From<PackedArrayAmbiPeptide<N>> for [AmbiAmino; N] {
fn from(packed_ambi_peptide: PackedArrayAmbiPeptide<N>) -> [AmbiAmino; N] {
(&packed_ambi_peptide).into()
}
}
impl<const N: usize> From<&PackedArrayAmbiPeptide<N>> for [AmbiAmino; N] {
fn from(packed_ambi_peptide: &PackedArrayAmbiPeptide<N>) -> [AmbiAmino; N] {
packed_ambi_peptide.0.map(AmbiAmino::decompress)
}
}
impl<'a, const N: usize> IntoIterator for &'a PackedArrayAmbiPeptide<N> {
type Item = AmbiAmino;
type IntoIter = PackedAmbiPeptideIter<'a>;
fn into_iter(self) -> Self::IntoIter {
PackedAmbiPeptideIter(self.0.iter())
}
}
impl<'a, const N: usize> IntoIterator for &'a mut PackedArrayAmbiPeptide<N> {
type Item = PackedAmbiAmino<'a>;
type IntoIter = PackedAmbiPeptideMutIter<'a>;
fn into_iter(self) -> Self::IntoIter {
PackedAmbiPeptideMutIter(self.0.iter_mut())
}
}
impl<const N: usize> IntoIterator for PackedArrayAmbiPeptide<N> {
type Item = AmbiAmino;
type IntoIter = PackedArrayAmbiPeptideIntoIter<N>;
fn into_iter(self) -> Self::IntoIter {
PackedArrayAmbiPeptideIntoIter(self.0.into_iter())
}
}
impl<const N: usize> PartialEq<PackedAmbiPeptide> for PackedArrayAmbiPeptide<N> {
fn eq(&self, other: &PackedAmbiPeptide) -> bool {
other == self
}
}
impl<const N: usize> PartialOrd<PackedAmbiPeptide> for PackedArrayAmbiPeptide<N> {
fn partial_cmp(&self, other: &PackedAmbiPeptide) -> Option<Ordering> {
other.partial_cmp(self).map(Ordering::reverse)
}
}
impl<const N: usize> PartialEq<PackedPeptide> for PackedArrayAmbiPeptide<N> {
fn eq(&self, other: &PackedPeptide) -> bool {
other == self
}
}
impl<const N: usize> PartialOrd<PackedPeptide> for PackedArrayAmbiPeptide<N> {
fn partial_cmp(&self, other: &PackedPeptide) -> Option<Ordering> {
other.partial_cmp(self).map(Ordering::reverse)
}
}
impl<const N: usize> PartialEq<PackedArrayPeptide<N>> for PackedArrayAmbiPeptide<N>
where
[(); N]: PackableArray,
{
fn eq(&self, other: &PackedArrayPeptide<N>) -> bool {
other == self
}
}
impl<const N: usize> PartialOrd<PackedArrayPeptide<N>> for PackedArrayAmbiPeptide<N>
where
[(); N]: PackableArray,
{
fn partial_cmp(&self, other: &PackedArrayPeptide<N>) -> Option<Ordering> {
other.partial_cmp(self).map(Ordering::reverse)
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize, const M: usize> PartialEq<[T; M]>
for PackedArrayAmbiPeptide<N>
{
fn eq(&self, other: &[T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize, const M: usize> PartialOrd<[T; M]>
for PackedArrayAmbiPeptide<N>
{
fn partial_cmp(&self, other: &[T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize, const M: usize> PartialEq<&mut [T; M]>
for PackedArrayAmbiPeptide<N>
{
fn eq(&self, other: &&mut [T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize, const M: usize> PartialOrd<&mut [T; M]>
for PackedArrayAmbiPeptide<N>
{
fn partial_cmp(&self, other: &&mut [T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize, const M: usize> PartialEq<&[T; M]>
for PackedArrayAmbiPeptide<N>
{
fn eq(&self, other: &&[T; M]) -> bool {
self.eq(&other.as_slice())
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize, const M: usize> PartialOrd<&[T; M]>
for PackedArrayAmbiPeptide<N>
{
fn partial_cmp(&self, other: &&[T; M]) -> Option<Ordering> {
self.partial_cmp(&other.as_slice())
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize> PartialEq<Vec<T>> for PackedArrayAmbiPeptide<N> {
fn eq(&self, other: &Vec<T>) -> bool {
self.eq(&&**other)
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize> PartialOrd<Vec<T>> for PackedArrayAmbiPeptide<N> {
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
self.partial_cmp(&&**other)
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize> PartialEq<&mut [T]> for PackedArrayAmbiPeptide<N> {
fn eq(&self, other: &&mut [T]) -> bool {
self.eq(&&**other)
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize> PartialOrd<&mut [T]> for PackedArrayAmbiPeptide<N> {
fn partial_cmp(&self, other: &&mut [T]) -> Option<Ordering> {
self.partial_cmp(&&**other)
}
}
impl<T: PartialEq<AmbiAmino>, const N: usize> PartialEq<&[T]> for PackedArrayAmbiPeptide<N> {
fn eq(&self, other: &&[T]) -> bool {
N == other.len() && self.iter().map(RefCmp).eq(*other)
}
}
impl<T: PartialOrd<AmbiAmino>, const N: usize> PartialOrd<&[T]> for PackedArrayAmbiPeptide<N> {
fn partial_cmp(&self, other: &&[T]) -> Option<Ordering> {
self.iter().map(RefCmp).partial_cmp(*other)
}
}
impl<const N: usize> PartialEq<&str> for PackedArrayAmbiPeptide<N> {
fn eq(&self, rhs: &&str) -> bool {
self == *rhs
}
}
impl<const N: usize> PartialEq<str> for PackedArrayAmbiPeptide<N> {
fn eq(&self, rhs: &str) -> bool {
self.iter().map(Ok).eq(iter_symbols(rhs))
}
}
impl<const N: usize> std::fmt::Display for PackedArrayAmbiPeptide<N> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
self.iter().fmt(f)
}
}
impl<const N: usize> std::fmt::Debug for PackedArrayAmbiPeptide<N> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedArrayAmbiPeptide")
.field(&display(self.iter()))
.finish()
}
}
#[derive(Clone)]
pub struct PackedAmbiPeptideIntoIter(std::vec::IntoIter<[u8; 3]>);
impl PackedAmbiPeptideIntoIter {
fn as_ref(&self) -> PackedAmbiPeptideIter<'_> {
PackedAmbiPeptideIter(self.0.as_slice().iter())
}
}
impl Iterator for PackedAmbiPeptideIntoIter {
type Item = AmbiAmino;
fn next(&mut self) -> Option<AmbiAmino> {
self.0.next().map(AmbiAmino::decompress)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl DoubleEndedIterator for PackedAmbiPeptideIntoIter {
fn next_back(&mut self) -> Option<AmbiAmino> {
self.0.next_back().map(AmbiAmino::decompress)
}
}
impl ExactSizeIterator for PackedAmbiPeptideIntoIter {
fn len(&self) -> usize {
self.0.len()
}
}
impl std::fmt::Display for PackedAmbiPeptideIntoIter {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
self.as_ref().fmt(f)
}
}
impl std::fmt::Debug for PackedAmbiPeptideIntoIter {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedAmbiPeptideIntoIter")
.field(&display(self.as_ref()))
.finish()
}
}
#[derive(Clone)]
pub struct PackedArrayAmbiPeptideIntoIter<const N: usize>(<[[u8; 3]; N] as IntoIterator>::IntoIter);
impl<const N: usize> PackedArrayAmbiPeptideIntoIter<N> {
fn as_ref(&self) -> PackedAmbiPeptideIter<'_> {
PackedAmbiPeptideIter(self.0.as_slice().iter())
}
}
impl<const N: usize> Iterator for PackedArrayAmbiPeptideIntoIter<N> {
type Item = AmbiAmino;
fn next(&mut self) -> Option<AmbiAmino> {
self.0.next().map(AmbiAmino::decompress)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<const N: usize> DoubleEndedIterator for PackedArrayAmbiPeptideIntoIter<N> {
fn next_back(&mut self) -> Option<AmbiAmino> {
self.0.next_back().map(AmbiAmino::decompress)
}
}
impl<const N: usize> ExactSizeIterator for PackedArrayAmbiPeptideIntoIter<N> {
fn len(&self) -> usize {
self.0.len()
}
}
impl<const N: usize> std::fmt::Display for PackedArrayAmbiPeptideIntoIter<N> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
self.as_ref().fmt(f)
}
}
impl<const N: usize> std::fmt::Debug for PackedArrayAmbiPeptideIntoIter<N> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedArrayAmbiPeptideIntoIter")
.field(&display(self.as_ref()))
.finish()
}
}
#[derive(Clone)]
pub struct PackedAmbiPeptideIter<'a>(std::slice::Iter<'a, [u8; 3]>);
impl Iterator for PackedAmbiPeptideIter<'_> {
type Item = AmbiAmino;
fn next(&mut self) -> Option<AmbiAmino> {
self.0.next().map(|&bytes| AmbiAmino::decompress(bytes))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl DoubleEndedIterator for PackedAmbiPeptideIter<'_> {
fn next_back(&mut self) -> Option<AmbiAmino> {
self.0
.next_back()
.map(|&bytes| AmbiAmino::decompress(bytes))
}
}
impl ExactSizeIterator for PackedAmbiPeptideIter<'_> {
fn len(&self) -> usize {
self.0.len()
}
}
impl std::fmt::Display for PackedAmbiPeptideIter<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
display(self.clone()).fmt(f)
}
}
impl std::fmt::Debug for PackedAmbiPeptideIter<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedAmbiPeptideIter")
.field(&display(self.clone()))
.finish()
}
}
pub struct PackedAmbiPeptideMutIter<'a>(std::slice::IterMut<'a, [u8; 3]>);
impl PackedAmbiPeptideMutIter<'_> {
fn read_values(&self) -> impl Iterator<Item = AmbiAmino> + Clone {
let slice = self.0.as_slice();
slice.iter().map(|&bytes| AmbiAmino::decompress(bytes))
}
}
impl<'a> Iterator for PackedAmbiPeptideMutIter<'a> {
type Item = PackedAmbiAmino<'a>;
fn next(&mut self) -> Option<PackedAmbiAmino<'a>> {
self.0.next().map(PackedAmbiAmino::new)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a> DoubleEndedIterator for PackedAmbiPeptideMutIter<'a> {
fn next_back(&mut self) -> Option<PackedAmbiAmino<'a>> {
self.0.next_back().map(PackedAmbiAmino::new)
}
}
impl ExactSizeIterator for PackedAmbiPeptideMutIter<'_> {
fn len(&self) -> usize {
self.0.len()
}
}
impl std::fmt::Display for PackedAmbiPeptideMutIter<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
display(self.read_values()).fmt(f)
}
}
impl std::fmt::Debug for PackedAmbiPeptideMutIter<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedAmbiPeptideMutIter")
.field(&display(self.read_values()))
.finish()
}
}
pub struct PackedAmbiAmino<'a> {
packed: &'a mut [u8; 3],
unpacked: AmbiAmino,
}
impl<'a> PackedAmbiAmino<'a> {
fn new(packed: &'a mut [u8; 3]) -> Self {
let unpacked = AmbiAmino::decompress(*packed);
Self { packed, unpacked }
}
}
impl Drop for PackedAmbiAmino<'_> {
fn drop(&mut self) {
*self.packed = self.unpacked.compress();
}
}
impl Deref for PackedAmbiAmino<'_> {
type Target = AmbiAmino;
fn deref(&self) -> &AmbiAmino {
&self.unpacked
}
}
impl DerefMut for PackedAmbiAmino<'_> {
fn deref_mut(&mut self) -> &mut AmbiAmino {
&mut self.unpacked
}
}
impl AsRef<AmbiAmino> for PackedAmbiAmino<'_> {
fn as_ref(&self) -> &AmbiAmino {
self
}
}
impl AsMut<AmbiAmino> for PackedAmbiAmino<'_> {
fn as_mut(&mut self) -> &mut AmbiAmino {
self
}
}
impl std::fmt::Display for PackedAmbiAmino<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
self.unpacked.fmt(f)
}
}
impl std::fmt::Debug for PackedAmbiAmino<'_> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_tuple("PackedAmbiAmino")
.field(&self.unpacked)
.finish()
}
}
#[cfg(test)]
mod tests {
use proptest::arbitrary::any;
use proptest::proptest;
use super::super::tests::{assert_both_roundtrips, assert_roundtrip};
use crate::proptest::{any_ambi_peptide, any_peptide};
use super::*;
#[test]
fn sanity_check_array_roundtrips() {
assert_both_roundtrips(&[] as &[AmbiAmino; 0]);
assert_both_roundtrips(&[AmbiAmino::A]);
assert_both_roundtrips(&[AmbiAmino::B, AmbiAmino::C]);
assert_both_roundtrips(&[AmbiAmino::D, AmbiAmino::E, AmbiAmino::F]);
assert_both_roundtrips(&AmbiAmino::arr(b"*SIGN"));
}
#[test]
fn smoke_test_iters() {
let ambi_peptide = AmbiAmino::seq(b"AMBI*PEPTIDE")[..].pack();
assert_eq!(Seq(Vec::from_iter(&ambi_peptide)), "AMBI*PEPTIDE");
assert_eq!(Seq(Vec::from_iter(ambi_peptide)), "AMBI*PEPTIDE");
let ambi_peptide = AmbiAmino::seq(b"AMBI*PEPTIDE").pack();
assert_eq!(Seq(Vec::from_iter(&ambi_peptide)), "AMBI*PEPTIDE");
assert_eq!(Seq(Vec::from_iter(ambi_peptide)), "AMBI*PEPTIDE");
}
#[test]
fn packed_ambi_peptide_eq_str() {
let dna = AmbiAmino::seq(b"AMBI*PEPTIDE")[..].pack();
assert_eq!(dna, "AMBI*PEPTIDE");
let dna = AmbiAmino::seq(b"AMBI*PEPTIDE").pack();
assert_eq!(dna, "AMBI*PEPTIDE");
}
#[test]
fn display() {
let ambi_peptide = AmbiAmino::seq(b"AMBI*PEPTIDE")[..].pack();
assert_eq!(ambi_peptide.to_string(), "AMBI*PEPTIDE");
assert_eq!(ambi_peptide.iter().to_string(), "AMBI*PEPTIDE");
assert_eq!(ambi_peptide.into_iter().to_string(), "AMBI*PEPTIDE");
let ambi_peptide = AmbiAmino::seq(b"AMBI*PEPTIDE").pack();
assert_eq!(ambi_peptide.to_string(), "AMBI*PEPTIDE");
assert_eq!(ambi_peptide.iter().to_string(), "AMBI*PEPTIDE");
assert_eq!(ambi_peptide.into_iter().to_string(), "AMBI*PEPTIDE");
}
proptest! {
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide_roundtrip(
ambi_peptide in any_ambi_peptide(1..25) ) {
assert_roundtrip(&*ambi_peptide);
}
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide_lexical_ordering(
peptide1 in any_ambi_peptide(0..50),
peptide2 in any_ambi_peptide(0..50),
) {
let packed1 = PackedAmbiPeptide::from(peptide1.as_slice());
let packed2 = PackedAmbiPeptide::from(peptide2.as_slice());
assert_eq!(packed1.0.cmp(&packed2.0), peptide1.cmp(&peptide2));
}
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide_length(
ambi_peptide in any_ambi_peptide(0..50)
) {
let packed = PackedAmbiPeptide::from(&ambi_peptide);
assert_eq!(packed.len(), ambi_peptide.len());
assert_eq!(packed.is_empty(), ambi_peptide.is_empty());
}
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide_ord_vs_slice(
ambi_peptide1 in any_ambi_peptide(0..50),
ambi_peptide2 in any_ambi_peptide(0..50),
) {
let packed1 = PackedAmbiPeptide::from(&ambi_peptide1);
assert_eq!(
packed1.partial_cmp(&ambi_peptide2),
ambi_peptide1.partial_cmp(&ambi_peptide2),
);
assert_eq!(packed1.eq(&ambi_peptide2), ambi_peptide1.eq(&ambi_peptide2));
}
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide_ord_vs_concrete_slice(
ambi_peptide1 in any_ambi_peptide(0..50),
peptide2 in any_peptide(0..50),
) {
let packed1 = PackedAmbiPeptide::from(&ambi_peptide1);
assert_eq!(
packed1.partial_cmp(&peptide2),
ambi_peptide1.iter().partial_cmp(&peptide2)
);
assert_eq!(packed1.eq(&peptide2), ambi_peptide1.eq(&peptide2));
}
#[cfg_attr(miri, ignore = "slow in miri; shouldn't touch unsafe code anyway")]
#[test]
fn packed_ambi_peptide5_ord(
ambi_peptide1 in any::<[AmbiAmino; 5]>(),
ambi_peptide2 in any_ambi_peptide(0..10),
) {
let packed1 = PackedArrayAmbiPeptide::from(&ambi_peptide1);
assert_eq!(
packed1.partial_cmp(&ambi_peptide2),
ambi_peptide1.as_slice().partial_cmp(&ambi_peptide2),
);
assert_eq!(packed1.eq(&ambi_peptide2), ambi_peptide1.as_slice().eq(&ambi_peptide2));
}
}
}