1use crate::traits::*;
10use common_traits::*;
11#[cfg(feature = "mem_dbg")]
12use mem_dbg::{MemDbg, MemSize};
13use std::io::{Read, Seek, SeekFrom, Write};
14
15#[derive(Debug, Clone)]
34#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
35pub struct WordAdapter<W: UnsignedInt + FromBytes + ToBytes, B> {
36 backend: B,
37 _marker: core::marker::PhantomData<W>,
38}
39
40impl<W: UnsignedInt + FromBytes + ToBytes, B> WordAdapter<W, B> {
41 pub fn new(backend: B) -> Self {
43 Self {
44 backend,
45 _marker: core::marker::PhantomData,
46 }
47 }
48
49 pub fn into_inner(self) -> B {
50 self.backend
51 }
52}
53
54impl<W: UnsignedInt + ToBytes + FromBytes + FiniteRangeNumber, B: Read> WordRead
55 for WordAdapter<W, B>
56{
57 type Error = std::io::Error;
58 type Word = W;
59
60 #[inline(always)]
61 fn read_word(&mut self) -> Result<W, Self::Error> {
62 let mut res: W::Bytes = Default::default();
63 self.backend
64 .read_exact(res.as_mut())
65 .map_err(|e|
66 match e.kind() {
67 std::io::ErrorKind::UnexpectedEof => {
68 std::io::Error::new(
69 e.kind(),
70 format!(concat!(
71 "Unexpected end of file. ",
72 "This might happen because the file length is not a multiple of the word size ({}). ",
73 "In this case, please pad with zeros at the end of the file. ",
74 "The inner std::io::Error was {:?}"), W::BYTES, e),
75 )
76 }
77 _ => e,
78 })?;
79 Ok(W::from_ne_bytes(res))
80 }
81}
82
83impl<W: UnsignedInt + ToBytes + FromBytes + FiniteRangeNumber, B: Write> WordWrite
84 for WordAdapter<W, B>
85{
86 type Error = std::io::Error;
87 type Word = W;
88
89 #[inline]
90 fn write_word(&mut self, word: W) -> Result<(), std::io::Error> {
91 let _ = self.backend.write(word.to_ne_bytes().as_ref())?;
92 Ok(())
93 }
94
95 fn flush(&mut self) -> Result<(), Self::Error> {
96 self.backend.flush()
97 }
98}
99
100impl<W: UnsignedInt + ToBytes + FromBytes + FiniteRangeNumber, B: Seek> WordSeek
101 for WordAdapter<W, B>
102{
103 type Error = std::io::Error;
104
105 #[inline(always)]
106 fn word_pos(&mut self) -> Result<u64, std::io::Error> {
107 Ok(self.backend.stream_position()?.div_ceil(W::BYTES as u64))
108 }
109
110 #[inline(always)]
111 fn set_word_pos(&mut self, word_index: u64) -> Result<(), std::io::Error> {
112 self.backend
113 .seek(SeekFrom::Start(word_index * W::BYTES as u64))?;
114 Ok(())
115 }
116}
117
118#[cfg(test)]
119mod test {
120 use crate::prelude::*;
121 #[test]
122 fn test_word_adapter() {
123 let data: Vec<u32> = vec![
124 0xa6032421, 0xc9d01b28, 0x168b4ecd, 0xc5ccbed9, 0xfd007100, 0x08469d41, 0x989fd8c2,
125 0x954d351a, 0x3225ec9f, 0xbca253f9, 0x915aad84, 0x274c0de1, 0x4bfc6982, 0x59a47341,
126 0x4e32a33a, 0x9e0d2208,
127 ];
128 let path = std::env::temp_dir().join("test_file_adapter");
129 {
130 let mut writer = <WordAdapter<u32, _>>::new(std::fs::File::create(&path).unwrap());
131 for value in &data {
132 writer.write_word(*value).unwrap();
133 }
134 }
135 {
136 let mut reader = <WordAdapter<u32, _>>::new(std::fs::File::open(&path).unwrap());
137 for value in &data {
138 assert_eq!(*value, reader.read_word().unwrap());
139 }
140 }
141 }
142
143 #[test]
144 fn test_word_adapter_codes() {
145 let data: Vec<u8> = vec![
146 0x5f, 0x68, 0xdb, 0xca, 0x79, 0x17, 0xf3, 0x37, 0x2c, 0x46, 0x63, 0xf7, 0xf3, 0x28,
147 0xa4, 0x8d, 0x29, 0x3b, 0xb6, 0xd5, 0xc7, 0xe2, 0x22, 0x3f, 0x6e, 0xb5, 0xf2, 0xda,
148 0x13, 0x1d, 0x37, 0x18, 0x5b, 0xf8, 0x45, 0x59, 0x33, 0x38, 0xaf, 0xc4, 0x8a, 0x1d,
149 0x78, 0x81, 0xc8, 0xc3, 0xdb, 0xab, 0x23, 0xe1, 0x13, 0xb0, 0x04, 0xd7, 0x3c, 0x21,
150 0x0e, 0xba, 0x5d, 0xfc, 0xac, 0x4f, 0x04, 0x2d,
151 ];
152 let path = std::env::temp_dir().join("test_file_adapter_codes");
153 {
154 let mut writer = <BufBitWriter<BE, _>>::new(<WordAdapter<u64, _>>::new(
155 std::fs::File::create(&path).unwrap(),
156 ));
157 for value in &data {
158 writer.write_gamma(*value as _).unwrap();
159 }
160 }
161 {
162 let mut reader = <BufBitReader<BE, _>>::new(<WordAdapter<u32, _>>::new(
163 std::fs::File::open(&path).unwrap(),
164 ));
165 for value in &data {
166 assert_eq!(*value as u64, reader.read_gamma().unwrap());
167 }
168 }
169 {
170 let mut writer = <BufBitWriter<LE, _>>::new(<WordAdapter<u64, _>>::new(
171 std::fs::File::create(&path).unwrap(),
172 ));
173 for value in &data {
174 writer.write_gamma(*value as _).unwrap();
175 }
176 }
177 {
178 let mut reader = <BufBitReader<LE, _>>::new(<WordAdapter<u32, _>>::new(
179 std::fs::File::open(&path).unwrap(),
180 ));
181 for value in &data {
182 assert_eq!(*value as u64, reader.read_gamma().unwrap());
183 }
184 }
185 }
186}