extern fn puts(message: *char) -> i32; extern fn malloc(size: u64) -> *u8; extern fn free(ptr: *u8); extern fn div(numerator: i32, denominator: i32) -> div_t; struct String { inner: *char, length: u64, max_length: u64, must_be_freed: bool, } impl String { pub fn new() -> String { String { inner: allocate(0), length: 0, max_length: 0, must_be_freed: true, } } pub fn from(str: *char) -> String { let length = str_length(str) as u64; let mut new = String::new(); let static = String { inner: str, length: length - 1, max_length: length, must_be_freed: false, }; concat_strings(&mut new, static); return new; } pub fn push(&mut self, other: String) { for i in 0 .. (str_length(other.inner) - 1) { add_char(self, other.inner[i]); } } pub fn add_char(&mut self, c: char) { if ((*self).length + 1) >= (*self).max_length { let new = allocate((*self).max_length + 4) as *char; copy_bits((*self).inner, new, (*self).max_length); if (*self).must_be_freed == true { free((*self).inner as *u8); } (*self).max_length = (*self).max_length + 4; (*self).inner = new; (*self).must_be_freed = true; } (*self).inner[(*self).length] = c; (((*self).inner) as *u8)[(*self).length + 1] = 0; (*self).length = (*self).length + 1; } pub fn push_num(&mut self, num: u64) { if num >= 10 { self.push_num(num / 10) } let rem = num % 10; if rem == 0 { self.add_char('0'); } else if rem == 1 { self.add_char('1'); } else if rem == 2 { self.add_char('2'); } else if rem == 3 { self.add_char('3'); } else if rem == 4 { self.add_char('4'); } else if rem == 5 { self.add_char('5'); } else if rem == 6 { self.add_char('6'); } else if rem == 7 { self.add_char('7'); } else if rem == 8 { self.add_char('8'); } else if rem == 9 { self.add_char('9'); } } pub fn free(&self) { free((*self).inner as *u8); } } impl binop (lhs: String) + (rhs: *char) -> String { let mut new = lhs; let added = from_str(rhs); concat_strings(&mut new, added); free_string(&added); return new; } impl binop (lhs: String) + (rhs: u64) -> String { let mut new = lhs; add_num_to_str(&mut new, rhs); return new; } struct div_t { quotient: i32, remainder: i32, } pub fn print(message: String) { puts(message.inner); } pub fn int_div(numerator: i32, denominator: i32) -> div_t { return div(numerator, denominator); } pub fn allocate(size: u64) -> *u8 { malloc(size) } pub fn new_string() -> String { String { inner: allocate(0), length: 0, max_length: 0, must_be_freed: true, } } pub fn from_str(str: *char) -> String { let length = str_length(str) as u64; let mut new = new_string(); let static = String { inner: str, length: length - 1, max_length: length, must_be_freed: false, }; concat_strings(&mut new, static); return new; } pub fn add_char(string: &mut String, c: char) { if ((*string).length + 1) >= (*string).max_length { let new = allocate((*string).max_length + 4) as *char; copy_bits((*string).inner, new, (*string).max_length); if (*string).must_be_freed == true { free((*string).inner as *u8); } (*string).max_length = (*string).max_length + 4; (*string).inner = new; (*string).must_be_freed = true; } (*string).inner[(*string).length] = c; (((*string).inner) as *u8)[(*string).length + 1] = 0; (*string).length = (*string).length + 1; } pub fn set_char(string: &mut String, c: char, position: u64) { if position <= (*string).length { (*string).inner[position] = c; } } pub fn free_string(string: &String) { free((*string).inner as *u8); } fn copy_bits(from: *char, to: *char, length: u64) { for i in 0 .. length { to[i] = from[i]; } } fn str_length(string: *char) -> u32 { let mut pos = 0; while ((string[pos] == '\0') == false) { pos = pos + 1; } return pos + 1; } pub fn add_num_to_str(string: &mut String, num: u64) { if num >= 10 { add_num_to_str(string, num / 10) } let rem = num % 10; if rem == 0 { add_char(string, '0'); } else if rem == 1 { add_char(string, '1'); } else if rem == 2 { add_char(string, '2'); } else if rem == 3 { add_char(string, '3'); } else if rem == 4 { add_char(string, '4'); } else if rem == 5 { add_char(string, '5'); } else if rem == 6 { add_char(string, '6'); } else if rem == 7 { add_char(string, '7'); } else if rem == 8 { add_char(string, '8'); } else if rem == 9 { add_char(string, '9'); } } pub fn concat_strings(destination: &mut String, source: String) { for i in 0 .. (str_length(source.inner) - 1) { add_char(destination, source.inner[i]); } } pub fn clamp(min: f32, max: f32, value: f32) -> f32 { if value > max { return max; } if value < min { return min; } return value; } pub fn abs(f: f32) -> f32 { if f < 0.0 { return f * (0.0 - 1.0); } return f; }