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
128
129
130
131
132
133
134
135
use core;
pub use brotli_decompressor::ffi::interface::{
  c_void
};
use brotli_decompressor::ffi::{
  slice_from_raw_parts_or_nil,
  slice_from_raw_parts_or_nil_mut,
};
use concat::BroCatli;
pub use concat::BroCatliResult;
pub type BroccoliResult = BroCatliResult;
// a tool to concatenate brotli files together

#[repr(C)]
pub struct BroccoliState {
    more_data: *mut c_void,
    current_data: [u8;120],
}

impl Clone for BroccoliState {
  fn clone(&self) -> BroccoliState {
    let mut cd = [0u8; 120];
    cd.clone_from_slice(&self.current_data[..]);
    BroccoliState{
      more_data:self.more_data,
      current_data:cd,
    }
  }
}

impl Copy for BroccoliState{}

impl Default for BroccoliState {
    fn default() -> BroccoliState {
        BroCatli::new().into()
    }
}
impl From<BroCatli> for BroccoliState {
    fn from(data: BroCatli) -> BroccoliState {
        let mut buffer = [0u8; 120];
        data.serialize_to_buffer(&mut buffer[..]).unwrap();
        BroccoliState{
            more_data: core::ptr::null_mut(),
            current_data:buffer,
        }
    }
}
impl Into<BroCatli> for BroccoliState {
    fn into(self) -> BroCatli {
        BroCatli::deserialize_from_buffer(&self.current_data[..]).unwrap()
    }
}

#[no_mangle]
pub extern fn BroccoliCreateInstance() -> BroccoliState {
    BroCatli::new().into()
}
#[no_mangle]
pub extern fn BroccoliCreateInstanceWithWindowSize(window_size: u8) -> BroccoliState {
    BroCatli::new_with_window_size(window_size).into()
}
#[no_mangle]
pub extern fn BroccoliDestroyInstance(_state: BroccoliState) {
}

#[no_mangle]
pub unsafe extern fn BroccoliNewBrotliFile(state: *mut BroccoliState) {
    let mut bro_catli: BroCatli = (*state).into();
    bro_catli.new_brotli_file();
    *state = BroccoliState::from(bro_catli);
}

#[no_mangle]
pub unsafe extern fn BroccoliConcatStream(
  state: *mut BroccoliState,
  available_in: *mut usize,
  input_buf_ptr: *mut*const u8,
  available_out: *mut usize,
  output_buf_ptr: *mut*mut u8) -> BroccoliResult {
  let input_buf = slice_from_raw_parts_or_nil(*input_buf_ptr, *available_in);
  let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out);
  let mut input_offset = 0usize;
  let mut output_offset = 0usize;
  let mut bro_catli: BroCatli = (*state).into();
  let ret = bro_catli.stream(input_buf, &mut input_offset, output_buf, &mut output_offset);
  *input_buf_ptr = (*input_buf_ptr).offset(input_offset as isize);
  *output_buf_ptr = (*output_buf_ptr).offset(output_offset as isize);
  *available_in -= input_offset;
  *available_out -= output_offset;
  *state = BroccoliState::from(bro_catli);
  ret
}

#[no_mangle]
pub unsafe extern fn BroccoliConcatStreaming(
  state: *mut BroccoliState,
  available_in: *mut usize,
  mut input_buf: *const u8,
  available_out: *mut usize,
  mut output_buf: *mut u8) -> BroccoliResult {
  BroccoliConcatStream(
    state,
    available_in,
    &mut input_buf,
    available_out,
    &mut output_buf)
      
}

#[no_mangle]
pub unsafe extern fn BroccoliConcatFinish(
  state: *mut BroccoliState,
  available_out: *mut usize,
  output_buf_ptr: *mut*mut u8) -> BroCatliResult {
  let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out);
  let mut output_offset = 0usize;
  let mut bro_catli: BroCatli = (*state).into();
  let ret = bro_catli.finish(output_buf, &mut output_offset);
  *output_buf_ptr = (*output_buf_ptr).offset(output_offset as isize);
  *available_out -= output_offset;
  *state = BroccoliState::from(bro_catli);
  ret
}

// exactly the same as BrotliConcatFinish but without the indirect
#[no_mangle]
pub unsafe extern fn BroccoliConcatFinished(
  state: *mut BroccoliState,
  available_out: *mut usize,
  mut output_buf: *mut u8) -> BroCatliResult {
  BroccoliConcatFinish(
    state,
    available_out,
    &mut output_buf)
}