1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum Trit {
12 Neg,
13 Zero,
14 Pos,
15}
16
17impl Trit {
18 pub fn to_i8(self) -> i8 {
19 match self {
20 Trit::Neg => -1,
21 Trit::Zero => 0,
22 Trit::Pos => 1,
23 }
24 }
25
26 pub fn from_i8(v: i8) -> Option<Self> {
27 match v {
28 -1 => Some(Trit::Neg),
29 0 => Some(Trit::Zero),
30 1 => Some(Trit::Pos),
31 _ => None,
32 }
33 }
34
35 pub fn digit(self) -> u8 {
37 match self {
38 Trit::Neg => 0,
39 Trit::Zero => 1,
40 Trit::Pos => 2,
41 }
42 }
43
44 pub fn from_digit(d: u8) -> Option<Self> {
45 match d {
46 0 => Some(Trit::Neg),
47 1 => Some(Trit::Zero),
48 2 => Some(Trit::Pos),
49 _ => None,
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
56pub struct TernarySequence {
57 trits: Vec<Trit>,
58}
59
60impl TernarySequence {
61 pub fn new(trits: Vec<Trit>) -> Self {
62 TernarySequence { trits }
63 }
64
65 pub fn from_i8(values: &[i8]) -> Self {
66 TernarySequence {
67 trits: values.iter()
68 .filter_map(|&v| Trit::from_i8(v))
69 .collect(),
70 }
71 }
72
73 pub fn len(&self) -> usize {
74 self.trits.len()
75 }
76
77 pub fn is_empty(&self) -> bool {
78 self.trits.is_empty()
79 }
80
81 pub fn trits(&self) -> &[Trit] {
82 &self.trits
83 }
84
85 pub fn push(&mut self, trit: Trit) {
86 self.trits.push(trit);
87 }
88
89 pub fn get(&self, idx: usize) -> Option<Trit> {
90 self.trits.get(idx).copied()
91 }
92
93 pub fn set(&mut self, idx: usize, trit: Trit) {
94 if idx < self.trits.len() {
95 self.trits[idx] = trit;
96 }
97 }
98
99 pub fn bit_capacity(&self, bits_per_trit: usize) -> usize {
101 self.trits.len() * bits_per_trit
102 }
103}
104
105pub struct BitEmbedder {
110 _bits_per_trit: usize,
111}
112
113impl BitEmbedder {
114 pub fn new(bits_per_trit: usize) -> Self {
115 BitEmbedder { _bits_per_trit: bits_per_trit.min(1) }
116 }
117
118 pub fn encode(&self, carrier: &TernarySequence, data: &[u8]) -> Option<TernarySequence> {
120 let bits_needed = data.len() * 8;
121 if bits_needed > carrier.len() {
122 return None;
123 }
124
125 let mut result = carrier.clone();
126 let mut bit_idx = 0;
127
128 for &byte in data {
129 for shift in (0..8).rev() {
130 let bit = (byte >> shift) & 1;
131 let trit = if bit == 1 { Trit::Pos } else { Trit::Neg };
132 result.set(bit_idx, trit);
133 bit_idx += 1;
134 }
135 }
136 Some(result)
137 }
138
139 pub fn decode(&self, encoded: &TernarySequence, byte_count: usize) -> Option<Vec<u8>> {
141 let mut result = Vec::with_capacity(byte_count);
142 let mut bit_idx = 0;
143
144 for _ in 0..byte_count {
145 let mut byte = 0u8;
146 for shift in (0..8).rev() {
147 let trit = encoded.get(bit_idx)?;
148 let bit = if trit == Trit::Pos { 1 } else { 0 };
149 byte |= bit << shift;
150 bit_idx += 1;
151 }
152 result.push(byte);
153 }
154 Some(result)
155 }
156}
157
158pub struct PatternEncoder {
162 pattern_len: usize,
164}
165
166impl PatternEncoder {
167 pub fn new(pattern_len: usize) -> Self {
168 PatternEncoder { pattern_len: pattern_len.max(2) }
169 }
170
171 pub fn encode(&self, message: &str) -> TernarySequence {
173 let mut trits = Vec::new();
174 for ch in message.chars() {
175 let code = ch as u32;
176 let ternary = Self::to_base3(code, self.pattern_len);
178 trits.extend_from_slice(&ternary);
179 }
180 TernarySequence::new(trits)
181 }
182
183 pub fn decode(&self, encoded: &TernarySequence) -> String {
185 let mut result = String::new();
186 let chunks = encoded.trits.chunks(self.pattern_len);
187 for chunk in chunks {
188 let code = Self::from_base3(chunk);
189 if let Some(ch) = char::from_u32(code) {
190 result.push(ch);
191 }
192 }
193 result
194 }
195
196 pub fn stego_encode(
198 &self,
199 carrier: &TernarySequence,
200 message: &str,
201 positions: &[usize],
202 ) -> Option<TernarySequence> {
203 let encoded = self.encode(message);
204 if encoded.len() > positions.len() {
205 return None;
206 }
207 let mut result = carrier.clone();
208 for (i, &pos) in positions.iter().enumerate() {
209 if i >= encoded.len() {
210 break;
211 }
212 if pos < result.len() {
213 result.set(pos, encoded.get(i)?);
214 }
215 }
216 Some(result)
217 }
218
219 pub fn stego_decode(
221 &self,
222 carrier: &TernarySequence,
223 positions: &[usize],
224 char_count: usize,
225 ) -> Option<String> {
226 let mut trits = Vec::new();
227 for &pos in positions {
228 if pos < carrier.len() {
229 trits.push(carrier.get(pos)?);
230 }
231 }
232 let seq = TernarySequence::new(trits);
233 let needed = char_count * self.pattern_len;
235 let truncated: Vec<Trit> = seq.trits.into_iter().take(needed).collect();
236 let seq = TernarySequence::new(truncated);
237 Some(self.decode(&seq))
238 }
239
240 fn to_base3(mut value: u32, len: usize) -> Vec<Trit> {
241 let mut digits = Vec::new();
242 while value > 0 {
243 digits.push(Trit::from_digit((value % 3) as u8).unwrap_or(Trit::Neg));
244 value /= 3;
245 }
246 while digits.len() < len {
247 digits.push(Trit::Neg); }
249 digits.truncate(len);
250 digits.reverse();
251 digits
252 }
253
254 fn from_base3(trits: &[Trit]) -> u32 {
255 let mut value = 0u32;
256 for &trit in trits {
257 value = value * 3 + trit.digit() as u32;
258 }
259 value
260 }
261}
262
263pub struct FrequencyModulator {
267 window_size: usize,
268}
269
270impl FrequencyModulator {
271 pub fn new(window_size: usize) -> Self {
272 FrequencyModulator { window_size: window_size.max(3) }
273 }
274
275 pub fn encode_byte(&self, byte: u8) -> Vec<Trit> {
277 let mut trits = Vec::with_capacity(self.window_size);
278 let neg_count = ((byte as usize) % self.window_size).min(self.window_size);
280 let pos_count = ((byte as usize / 3) % self.window_size).min(self.window_size.saturating_sub(neg_count));
281 let zero_count = self.window_size - neg_count - pos_count;
282
283 for _ in 0..neg_count {
284 trits.push(Trit::Neg);
285 }
286 for _ in 0..zero_count {
287 trits.push(Trit::Zero);
288 }
289 for _ in 0..pos_count {
290 trits.push(Trit::Pos);
291 }
292 trits
293 }
294
295 pub fn decode_byte(&self, trits: &[Trit]) -> u8 {
297 let neg_count = trits.iter().filter(|&&t| t == Trit::Neg).count();
298 let pos_count = trits.iter().filter(|&&t| t == Trit::Pos).count();
299 ((neg_count + pos_count * 3) % 256) as u8
300 }
301
302 pub fn encode(&self, carrier: &TernarySequence, data: &[u8]) -> Option<TernarySequence> {
304 let needed = data.len() * self.window_size;
305 if needed > carrier.len() {
306 return None;
307 }
308
309 let mut result = carrier.clone();
310 for (i, &byte) in data.iter().enumerate() {
311 let window = self.encode_byte(byte);
312 let offset = i * self.window_size;
313 for (j, trit) in window.iter().enumerate() {
314 result.set(offset + j, *trit);
315 }
316 }
317 Some(result)
318 }
319
320 pub fn decode(&self, carrier: &TernarySequence, byte_count: usize) -> Vec<u8> {
322 let mut result = Vec::with_capacity(byte_count);
323 for i in 0..byte_count {
324 let offset = i * self.window_size;
325 if offset + self.window_size > carrier.len() {
326 break;
327 }
328 let window: Vec<Trit> = (offset..offset + self.window_size)
329 .filter_map(|j| carrier.get(j))
330 .collect();
331 result.push(self.decode_byte(&window));
332 }
333 result
334 }
335}
336
337pub struct StatisticalStego {
341 block_size: usize,
342}
343
344impl StatisticalStego {
345 pub fn new(block_size: usize) -> Self {
346 StatisticalStego { block_size: block_size.max(3) }
347 }
348
349 pub fn block_stats(trits: &[Trit]) -> (f64, f64, f64) {
351 let n = trits.len() as f64;
352 if n == 0.0 {
353 return (0.0, 0.0, 0.0);
354 }
355 let neg = trits.iter().filter(|&&t| t == Trit::Neg).count() as f64 / n;
356 let zero = trits.iter().filter(|&&t| t == Trit::Zero).count() as f64 / n;
357 let pos = trits.iter().filter(|&&t| t == Trit::Pos).count() as f64 / n;
358 (neg, zero, pos)
359 }
360
361 pub fn encode_bit(&self, block: &mut [Trit], bit: u8) {
363 if block.len() < self.block_size {
364 return;
365 }
366 match bit {
368 0 => {
369 for i in 0..block.len() / 2 {
371 block[i] = Trit::Neg;
372 }
373 }
374 1 => {
375 for i in 0..block.len() / 2 {
377 block[i] = Trit::Pos;
378 }
379 }
380 _ => {}
381 }
382 }
383
384 pub fn decode_bit(&self, block: &[Trit]) -> u8 {
386 let (neg, _, pos) = Self::block_stats(block);
387 if pos > neg {
388 1
389 } else {
390 0
391 }
392 }
393
394 pub fn encode(&self, carrier: &TernarySequence, data: &[u8]) -> Option<TernarySequence> {
396 let bits_needed = data.len() * 8;
397 if bits_needed * self.block_size > carrier.len() {
398 return None;
399 }
400
401 let mut trits = carrier.trits.clone();
402 for (byte_idx, &byte) in data.iter().enumerate() {
403 for bit_idx in 0..8 {
404 let bit = (byte >> (7 - bit_idx)) & 1;
405 let offset = (byte_idx * 8 + bit_idx) * self.block_size;
406 let end = (offset + self.block_size).min(trits.len());
407 if offset < trits.len() {
408 self.encode_bit(&mut trits[offset..end], bit);
409 }
410 }
411 }
412 Some(TernarySequence::new(trits))
413 }
414
415 pub fn decode(&self, encoded: &TernarySequence, byte_count: usize) -> Vec<u8> {
417 let mut result = Vec::with_capacity(byte_count);
418 for byte_idx in 0..byte_count {
419 let mut byte = 0u8;
420 for bit_idx in 0..8 {
421 let offset = (byte_idx * 8 + bit_idx) * self.block_size;
422 let end = (offset + self.block_size).min(encoded.len());
423 if offset >= encoded.len() {
424 break;
425 }
426 let block: Vec<Trit> = (offset..end)
427 .filter_map(|j| encoded.get(j))
428 .collect();
429 let bit = self.decode_bit(&block);
430 byte |= bit << (7 - bit_idx);
431 }
432 result.push(byte);
433 }
434 result
435 }
436}
437
438pub struct SpreadSpectrum {
442 key: Vec<usize>,
443 chip_rate: usize,
444}
445
446impl SpreadSpectrum {
447 pub fn new(key: Vec<usize>, chip_rate: usize) -> Self {
448 SpreadSpectrum { key, chip_rate: chip_rate.max(1) }
449 }
450
451 pub fn generate_pattern(&self, length: usize) -> Vec<Trit> {
453 let mut pattern = Vec::with_capacity(length);
454 for i in 0..length {
455 let key_byte = self.key[i % self.key.len()];
456 let val = (key_byte.wrapping_add(i)).wrapping_mul(31) % 3;
457 pattern.push(Trit::from_digit(val as u8).unwrap_or(Trit::Zero));
458 }
459 pattern
460 }
461
462 pub fn encode_bit(&self, bit: u8, pattern: &[Trit]) -> Vec<Trit> {
464 let sign = if bit == 1 { 1i8 } else { -1i8 };
465 pattern.iter().map(|&t| {
466 let v = t.to_i8() * sign;
467 Trit::from_i8(v.clamp(-1, 1)).unwrap_or(Trit::Zero)
468 }).collect()
469 }
470
471 pub fn decode_bit(&self, encoded: &[Trit], pattern: &[Trit]) -> u8 {
473 let correlation: i64 = encoded.iter().zip(pattern.iter())
474 .map(|(&e, &p)| e.to_i8() as i64 * p.to_i8() as i64)
475 .sum();
476 if correlation > 0 { 1 } else { 0 }
477 }
478
479 pub fn encode(&self, carrier: &TernarySequence, data: &[u8]) -> Option<TernarySequence> {
481 let bits_needed = data.len() * 8;
482 let needed = bits_needed * self.chip_rate;
483 if needed > carrier.len() {
484 return None;
485 }
486
487 let mut trits = carrier.trits.clone();
488 let pattern = self.generate_pattern(self.chip_rate);
489
490 for (byte_idx, &byte) in data.iter().enumerate() {
491 for bit_idx in 0..8 {
492 let bit = (byte >> (7 - bit_idx)) & 1;
493 let encoded_bit = self.encode_bit(bit, &pattern);
494 let offset = (byte_idx * 8 + bit_idx) * self.chip_rate;
495 for (j, trit) in encoded_bit.iter().enumerate() {
496 if offset + j < trits.len() {
497 trits[offset + j] = *trit;
498 }
499 }
500 }
501 }
502 Some(TernarySequence::new(trits))
503 }
504
505 pub fn decode(&self, encoded: &TernarySequence, byte_count: usize) -> Vec<u8> {
507 let pattern = self.generate_pattern(self.chip_rate);
508 let mut result = Vec::with_capacity(byte_count);
509
510 for byte_idx in 0..byte_count {
511 let mut byte = 0u8;
512 for bit_idx in 0..8 {
513 let offset = (byte_idx * 8 + bit_idx) * self.chip_rate;
514 if offset + self.chip_rate > encoded.len() {
515 break;
516 }
517 let chunk: Vec<Trit> = (offset..offset + self.chip_rate)
518 .filter_map(|j| encoded.get(j))
519 .collect();
520 let bit = self.decode_bit(&chunk, &pattern);
521 byte |= bit << (7 - bit_idx);
522 }
523 result.push(byte);
524 }
525 result
526 }
527}
528
529pub struct CapacityAnalyzer;
533
534impl CapacityAnalyzer {
535 pub fn max_bytes(seq_len: usize, technique: &str) -> usize {
537 match technique {
538 "bit" => seq_len / 8,
539 "pattern" => seq_len / 7, "frequency" => seq_len / 9, "statistical" => seq_len / (8 * 4), "spread" => seq_len / (8 * 8), _ => 0,
544 }
545 }
546
547 pub fn embedding_efficiency(data_len: usize, modified_trits: usize) -> f64 {
549 if modified_trits == 0 {
550 return 0.0;
551 }
552 (data_len as f64 * 8.0) / modified_trits as f64
553 }
554
555 pub fn detect_anomaly(seq: &TernarySequence) -> f64 {
557 let (neg, zero, pos) = StatisticalStego::block_stats(seq.trits());
558 let expected = 1.0 / 3.0;
560 let deviation = (neg - expected).abs() + (zero - expected).abs() + (pos - expected).abs();
561 deviation / 2.0 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 #[test]
571 fn test_trit_conversions() {
572 assert_eq!(Trit::Neg.to_i8(), -1);
573 assert_eq!(Trit::Zero.to_i8(), 0);
574 assert_eq!(Trit::Pos.to_i8(), 1);
575 assert_eq!(Trit::from_i8(-1), Some(Trit::Neg));
576 assert_eq!(Trit::from_i8(5), None);
577 }
578
579 #[test]
580 fn test_trit_digits() {
581 assert_eq!(Trit::Neg.digit(), 0);
582 assert_eq!(Trit::Zero.digit(), 1);
583 assert_eq!(Trit::Pos.digit(), 2);
584 assert_eq!(Trit::from_digit(0), Some(Trit::Neg));
585 assert_eq!(Trit::from_digit(3), None);
586 }
587
588 #[test]
589 fn test_ternary_sequence_basic() {
590 let seq = TernarySequence::from_i8(&[-1, 0, 1, -1, 0]);
591 assert_eq!(seq.len(), 5);
592 assert_eq!(seq.get(0), Some(Trit::Neg));
593 assert_eq!(seq.get(2), Some(Trit::Pos));
594 assert!(!seq.is_empty());
595 }
596
597 #[test]
598 fn test_ternary_sequence_push() {
599 let mut seq = TernarySequence::new(vec![]);
600 seq.push(Trit::Pos);
601 seq.push(Trit::Neg);
602 assert_eq!(seq.len(), 2);
603 assert_eq!(seq.get(0), Some(Trit::Pos));
604 }
605
606 #[test]
607 fn test_bit_embedder_encode_decode() {
608 let carrier = TernarySequence::from_i8(&[0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1]);
609 let embedder = BitEmbedder::new(1);
610 let data = vec![0x41]; let encoded = embedder.encode(&carrier, &data).unwrap();
612 let decoded = embedder.decode(&encoded, 1).unwrap();
613 assert_eq!(decoded, data);
614 }
615
616 #[test]
617 fn test_bit_embedder_insufficient_capacity() {
618 let carrier = TernarySequence::from_i8(&[0, 1]);
619 let embedder = BitEmbedder::new(1);
620 let data = vec![0xFF, 0xFF];
621 assert!(embedder.encode(&carrier, &data).is_none());
622 }
623
624 #[test]
625 fn test_bit_embedder_multiple_bytes() {
626 let carrier = TernarySequence::from_i8(&[0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1]);
627 let embedder = BitEmbedder::new(1);
628 let data = vec![0x48, 0x69]; let encoded = embedder.encode(&carrier, &data).unwrap();
630 let decoded = embedder.decode(&encoded, 2).unwrap();
631 assert_eq!(decoded, data);
632 }
633
634 #[test]
635 fn test_pattern_encoder_basic() {
636 let encoder = PatternEncoder::new(6);
637 let encoded = encoder.encode("AB");
638 let decoded = encoder.decode(&encoded);
639 assert_eq!(decoded, "AB");
640 }
641
642 #[test]
643 fn test_pattern_encoder_empty() {
644 let encoder = PatternEncoder::new(4);
645 let encoded = encoder.encode("");
646 assert_eq!(encoded.len(), 0);
647 let decoded = encoder.decode(&encoded);
648 assert_eq!(decoded, "");
649 }
650
651 #[test]
652 fn test_pattern_stego_encode_decode() {
653 let carrier = TernarySequence::from_i8(&[0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1]);
654 let encoder = PatternEncoder::new(4);
655 let positions = vec![0, 1, 2, 3, 4, 5, 6, 7];
656 let encoded = encoder.stego_encode(&carrier, "A", &positions).unwrap();
657 assert_eq!(encoded.len(), carrier.len());
658 }
659
660 #[test]
661 fn test_frequency_modulator_encode_byte() {
662 let modulator = FrequencyModulator::new(6);
663 let trits = modulator.encode_byte(0x41);
664 assert_eq!(trits.len(), 6);
665 }
666
667 #[test]
668 fn test_frequency_modulator_roundtrip() {
669 let carrier = TernarySequence::from_i8(&[0; 36]);
670 let modulator = FrequencyModulator::new(9);
671 let data = vec![0x41, 0x42, 0x43, 0x00];
672 let encoded = modulator.encode(&carrier, &data).unwrap();
673 let decoded = modulator.decode(&encoded, 4);
674 assert_eq!(decoded.len(), 4);
676 }
677
678 #[test]
679 fn test_frequency_modulator_insufficient() {
680 let carrier = TernarySequence::from_i8(&[0; 3]);
681 let modulator = FrequencyModulator::new(9);
682 let data = vec![0x41, 0x42];
683 assert!(modulator.encode(&carrier, &data).is_none());
684 }
685
686 #[test]
687 fn test_statistical_stego_block_stats() {
688 let trits = vec![Trit::Neg, Trit::Neg, Trit::Zero, Trit::Pos];
689 let (neg, zero, pos) = StatisticalStego::block_stats(&trits);
690 assert!((neg - 0.5).abs() < 0.01);
691 assert!((zero - 0.25).abs() < 0.01);
692 assert!((pos - 0.25).abs() < 0.01);
693 }
694
695 #[test]
696 fn test_statistical_stego_bit() {
697 let stego = StatisticalStego::new(8);
698 let mut block = vec![Trit::Zero; 8];
699 stego.encode_bit(&mut block, 1);
700 assert_eq!(stego.decode_bit(&block), 1);
701 stego.encode_bit(&mut block, 0);
702 assert_eq!(stego.decode_bit(&block), 0);
703 }
704
705 #[test]
706 fn test_statistical_stego_roundtrip() {
707 let carrier = TernarySequence::from_i8(&[0; 256]);
708 let stego = StatisticalStego::new(4);
709 let data = vec![0xAB];
710 let encoded = stego.encode(&carrier, &data).unwrap();
711 let decoded = stego.decode(&encoded, 1);
712 assert_eq!(decoded, data);
713 }
714
715 #[test]
716 fn test_spread_spectrum_pattern() {
717 let ss = SpreadSpectrum::new(vec![42, 17, 99], 8);
718 let pattern = ss.generate_pattern(10);
719 assert_eq!(pattern.len(), 10);
720 for t in &pattern {
722 assert!(matches!(t, Trit::Neg | Trit::Zero | Trit::Pos));
723 }
724 }
725
726 #[test]
727 fn test_spread_spectrum_bit() {
728 let ss = SpreadSpectrum::new(vec![42, 17], 8);
729 let pattern = ss.generate_pattern(8);
730 let encoded = ss.encode_bit(1, &pattern);
731 assert_eq!(ss.decode_bit(&encoded, &pattern), 1);
732 let encoded0 = ss.encode_bit(0, &pattern);
733 assert_eq!(ss.decode_bit(&encoded0, &pattern), 0);
734 }
735
736 #[test]
737 fn test_spread_spectrum_roundtrip() {
738 let carrier = TernarySequence::from_i8(&[0; 128]);
739 let ss = SpreadSpectrum::new(vec![42, 17, 99], 8);
740 let data = vec![0x48];
741 let encoded = ss.encode(&carrier, &data).unwrap();
742 let decoded = ss.decode(&encoded, 1);
743 assert_eq!(decoded, data);
744 }
745
746 #[test]
747 fn test_capacity_analyzer() {
748 assert_eq!(CapacityAnalyzer::max_bytes(100, "bit"), 12);
749 assert_eq!(CapacityAnalyzer::max_bytes(100, "pattern"), 14);
750 assert!(CapacityAnalyzer::max_bytes(100, "unknown") == 0);
751 }
752
753 #[test]
754 fn test_embedding_efficiency() {
755 let eff = CapacityAnalyzer::embedding_efficiency(1, 8);
756 assert!((eff - 1.0).abs() < 0.01);
757 }
758
759 #[test]
760 fn test_detect_anomaly_uniform() {
761 let trits: Vec<Trit> = (0..99).map(|i| match i % 3 {
763 0 => Trit::Neg,
764 1 => Trit::Zero,
765 _ => Trit::Pos,
766 }).collect();
767 let seq = TernarySequence::new(trits);
768 let anomaly = CapacityAnalyzer::detect_anomaly(&seq);
769 assert!(anomaly < 0.1); }
771
772 #[test]
773 fn test_detect_anomaly_biased() {
774 let trits = vec![Trit::Pos; 100];
775 let seq = TernarySequence::new(trits);
776 let anomaly = CapacityAnalyzer::detect_anomaly(&seq);
777 assert!(anomaly > 0.5); }
779}