1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2019 FaultyRAM
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. This file may not be copied,
// modified, or distributed except according to those terms.
//! Provides support for the Redshirt 1 and Redshirt 2 data encoding schemes.
//!
//! This crate provides utilities for reading and writing Redshirt 1- or Redshirt 2-encoded data.
//! The Redshirt encoding schemes are used in *Uplink*, a 2001 computer hacking simulation game
//! developed by Introversion Software.
//!
//! # Reading Redshirt data
//!
//! redshirt provides `v1::Reader` for reading Redshirt 1 streams, and `v2::Reader` for reading
//! Redshirt 2 streams:
//!
//! ```no_run
//! use redshirt::v1::Reader;
//! use std::{fs::OpenOptions, io::Read};
//!
//! fn main() {
//! let file = OpenOptions::new().read(true).open("data.dat").unwrap();
//! let mut reader = Reader::new(file).unwrap();
//! let mut buffer = [u8::default(); 4];
//! reader.read_exact(&mut buffer).unwrap();
//! println!("{:#?}", buffer);
//! }
//! ```
//!
//! Both types offer the same features: support for reading and seeking via the standard `Read` and
//! `Seek` traits, and destructuring to the underlying reader via `Reader::into_inner`.
//!
//! # Writing Redshirt data
//!
//! redshirt provides `v1::Writer` for writing Redshirt 1 streams, and `v2::Writer` for writing
//! Redshirt 2 streams:
//!
//! ```no_run
//! use redshirt::v1::Writer;
//! use std::{fs::OpenOptions, io::Write};
//!
//! fn main() {
//! let file = OpenOptions::new().write(true).open("data.dat").unwrap();
//! let mut writer = Writer::new(file).unwrap();
//! let data = b"foobar";
//! writer.write_all(&data[..]).unwrap();
//! }
//! ```
//!
//! Both types support writing via the standard `Write` trait, and destructuring to the underlying
//! writer via `Writer::into_inner`. `v1::Writer` also supports seeking via the standard `Seek`
//! trait. (See below for why `v2::Writer` doesn't support seeking.)
//!
//! ## `v2::Writer` additional notes
//!
//! Redshirt 2 stores a [SHA-1] hash of the encoded data in the header. This means that using
//! `v2::Writer` (which writes Redshirt 2 data) has two implications:
//!
//! * Seeking isn't supported, because it's costly to implement; the data would need to be re-read,
//! and possibly stored in heap memory, in order to generate a correct hash.
//! * Currently the SHA-1 hash is finalised and written into the header either when the `v2::Writer`
//! is dropped, or when `v2::Writer::into_inner` is called.
//! **The `drop` call will panic if an error occurs**, so it's highly recommended that you call
//! `into_inner`, which returns a `Result<T, Error>` instead:
//!
//! ```no_run
//! use redshirt::v2::Writer;
//! use std::{fs::OpenOptions, io::Write};
//!
//! fn main() {
//! let file = OpenOptions::new().write(true).open("User.usr").unwrap();
//! let mut writer = Writer::new(file).unwrap();
//! let data = b"foobar";
//! writer.write_all(&data[..]).unwrap();
//! let _ = writer.into_inner().unwrap(); // Triggers a panic if writing the checksum fails.
//! }
//! ```
//!
//! [SHA-1]: https://en.wikipedia.org/wiki/SHA-1
pub
pub use Error;