sftp-protocol 0.1.0

A pure Rust implementation of the SFTP protocol
Documentation
use proptest::bits::BitSetLike;
use proptest::bits::BitSetStrategy;
use proptest::prelude::any;
use proptest::prelude::Arbitrary;
use proptest::prelude::BoxedStrategy;
use proptest::prelude::Just;
use proptest::strategy::Strategy;

use super::FileAttributes;
use super::FileAttrFlags;

impl BitSetLike for FileAttrFlags /* {{{ */ {
	fn new_bitset(_max: usize) -> Self {
		Self::empty()
	}

	fn len(&self) -> usize {
		32
	}

	fn test(&self, i: usize) -> bool {
		(self.bits() & 2 << i) != 0
	}

	fn set(&mut self, i: usize) {
		self.insert(Self::from_bits_truncate(2 << i))
	}

	fn clear(&mut self, i: usize) {
		self.remove(Self::from_bits_truncate(2 << i))
	}
} // }}}

impl Arbitrary for FileAttrFlags {
	type Parameters = ();
	type Strategy = BitSetStrategy<Self>;
	fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
		BitSetStrategy::masked(Self::from_bits_truncate(0x8000000f))
	}
}

impl Arbitrary for FileAttributes {
	type Parameters = ();
	type Strategy = BoxedStrategy<Self>;
	fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
		FileAttrFlags::arbitrary_with(())
			.prop_flat_map(|flags| {
				let size = match flags.contains(FileAttrFlags::Size) {
					true => any::<u64>().prop_map(Some).boxed(),
					false => Just(None).boxed()
				};
				let (uid, gid) = match flags.contains(FileAttrFlags::UidGid) {
					true => (any::<u32>().prop_map(Some).boxed(), any::<u32>().prop_map(Some).boxed()),
					false => (Just(None).boxed(), Just(None).boxed())
				};
				let permissions = match flags.contains(FileAttrFlags::Permissions) {
					true => any::<u32>().prop_map(Some).boxed(),
					false => Just(None).boxed()
				};
				let (atime, mtime) = match flags.contains(FileAttrFlags::ACModTime) {
					true => (any::<u32>().prop_map(Some).boxed(), any::<u32>().prop_map(Some).boxed()),
					false => (Just(None).boxed(), Just(None).boxed())
				};
				(Just(flags), size, uid, gid, permissions, atime, mtime)
			})
			.prop_map(|(flags, size, uid, gid, permissions, atime, mtime)| {
				FileAttributes{
					flags,
					size,
					uid,
					gid,
					permissions: permissions.map(|p| p.into()),
					atime,
					mtime
				}
			})
			.boxed()
	}
}