use bitvec::prelude::*;
use crate::{PerCodecData, PerCodecError};
#[allow(unused)]
use crate::per::common::encode::*;
pub fn encode_choice_idx(
data: &mut PerCodecData,
lb: i128,
ub: i128,
is_extensible: bool,
idx: i128,
extended: bool,
) -> Result<(), PerCodecError> {
encode_choice_idx_common(data, lb, ub, is_extensible, idx, extended, false)
}
pub fn encode_sequence_header(
data: &mut PerCodecData,
is_extensible: bool,
optionals: &BitSlice<u8, Msb0>,
extended: bool,
) -> Result<(), PerCodecError> {
encode_sequence_header_common(data, is_extensible, optionals, extended, false)
}
pub fn encode_integer(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: i128,
extended: bool,
) -> Result<(), PerCodecError> {
encode_integer_common(data, lb, ub, is_extensible, value, extended, false)
}
pub fn encode_bool(data: &mut PerCodecData, value: bool) -> Result<(), PerCodecError> {
encode_bool_common(data, value, true)
}
pub fn encode_enumerated(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: i128,
extended: bool,
) -> Result<(), PerCodecError> {
encode_enumerated_common(data, lb, ub, is_extensible, value, extended, false)
}
pub fn encode_bitstring(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
bit_string: &BitSlice<u8, Msb0>,
extended: bool,
) -> Result<(), PerCodecError> {
encode_bitstring_common(data, lb, ub, is_extensible, bit_string, extended, false)
}
pub fn encode_octetstring(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
octet_string: &Vec<u8>,
extended: bool,
) -> Result<(), PerCodecError> {
encode_octet_string_common(data, lb, ub, is_extensible, octet_string, extended, false)
}
pub fn encode_length_determinent(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
normally_small: bool,
value: usize,
) -> Result<(), PerCodecError> {
encode_length_determinent_common(data, lb, ub, normally_small, value, false)
}
pub fn encode_visible_string(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: &String,
extended: bool,
) -> Result<(), PerCodecError> {
encode_ascii_ish_string_common(data, lb, ub, is_extensible, value, extended)
}
pub fn encode_printable_string(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: &String,
extended: bool,
) -> Result<(), PerCodecError> {
encode_ascii_ish_string_common(data, lb, ub, is_extensible, value, extended)
}
pub fn encode_utf8_string(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: &String,
extended: bool,
) -> Result<(), PerCodecError> {
encode_octet_string_common(
data,
lb,
ub,
is_extensible,
value.as_bytes(),
extended,
false,
)
}
fn encode_ascii_ish_string_common(
data: &mut PerCodecData,
lb: Option<i128>,
ub: Option<i128>,
is_extensible: bool,
value: &str,
extended: bool,
) -> Result<(), PerCodecError> {
if extended {
return Err(PerCodecError::new(
"Encode of extended octetstring not yet implemented",
));
}
if is_extensible {
data.encode_bool(extended);
}
encode_length_determinent_common(data, lb, ub, false, value.len(), false)?;
let bits_per_char = 7;
let offset = 8 - bits_per_char;
let chars_vec = value
.chars()
.map(|c| BitSlice::<_, Msb0>::from_element(&(c as u8))[offset..].to_bitvec())
.collect::<Vec<_>>()
.into_iter()
.flatten()
.collect::<BitVec<u8, Msb0>>();
data.append_bits(chars_vec.as_bitslice());
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode_bool_always_success() {
let mut data = PerCodecData::new_uper();
let result = encode_bool(&mut data, true);
assert!(result.is_ok());
assert_eq!(data.bits.len(), 1);
assert_eq!(data.bits[0], true);
}
#[test]
fn int_too_small() {
assert!(encode_integer(
&mut PerCodecData::new_uper(),
Some(1),
None,
false,
0,
false
)
.is_err());
}
#[test]
fn int_too_big() {
assert!(encode_integer(
&mut PerCodecData::new_uper(),
Some(-1),
Some(0),
false,
1,
false
)
.is_err());
}
#[test]
fn octetstring_too_small() {
assert!(encode_octetstring(
&mut PerCodecData::new_uper(),
Some(2),
None,
false,
&vec![0],
false
)
.is_err());
}
#[test]
fn octetstring_too_big() {
assert!(encode_octetstring(
&mut PerCodecData::new_uper(),
None,
Some(1),
false,
&vec![0, 0],
false
)
.is_err());
}
#[test]
fn string_too_small() {
assert!(encode_visible_string(
&mut PerCodecData::new_uper(),
Some(2),
None,
false,
&"a".to_string(),
false
)
.is_err());
}
#[test]
fn string_too_big() {
assert!(encode_visible_string(
&mut PerCodecData::new_uper(),
None,
Some(1),
false,
&"aa".to_string(),
false
)
.is_err());
}
#[test]
fn length_too_small() {
assert!(
encode_length_determinent(&mut PerCodecData::new_uper(), Some(2), None, false, 1,)
.is_err()
);
}
#[test]
fn length_too_big() {
assert!(
encode_length_determinent(&mut PerCodecData::new_uper(), None, Some(1), false, 2,)
.is_err()
);
}
#[test]
fn big_length_too_big() {
assert!(encode_length_determinent(
&mut PerCodecData::new_uper(),
None,
Some(65536),
false,
65537,
)
.is_err());
}
#[test]
fn bitstring_too_small() {
assert!(encode_bitstring(
&mut PerCodecData::new_uper(),
Some(2),
None,
false,
bits![u8, Msb0; 0],
false
)
.is_err());
}
#[test]
fn bitstring_too_big() {
assert!(encode_bitstring(
&mut PerCodecData::new_uper(),
None,
Some(1),
false,
bits![u8, Msb0; 0, 0],
false
)
.is_err());
}
#[test]
fn bitstring_uper_ascii_ish_string() {
let value = "John".to_string();
let mut codec_data = &mut PerCodecData::new_uper();
let result = encode_visible_string(&mut codec_data, None, None, false, &value, false);
assert!(result.is_ok(), "{:#?}", result.err().unwrap());
}
}