use bitvec::prelude::*;
use turtle::Turtle;
static TEXT: &str = "Β‘Hola, mundo! πππ";
const NUMBER: f64 = std::f64::consts::PI;
const BIT_WIDTH: f64 = 20.0;
const BIT_HEIGHT: f64 = 10.0;
const BIT_MARGIN: f64 = BIT_WIDTH / 2.0;
const BIT_BOX: f64 = BIT_WIDTH + BIT_MARGIN;
fn main() {
let mut turtle = Turtle::new();
turtle.pen_up();
let right_edge = BIT_BOX * 8.0 / 2.0;
let byte_rows = TEXT.len();
let char_gaps = TEXT.chars().count();
let top_edge = BIT_HEIGHT * ((byte_rows + char_gaps) as f64 / 2.0);
turtle.forward(top_edge);
turtle.right(90.0);
turtle.forward(right_edge);
turtle.left(180.0);
draw_text(&mut turtle, TEXT);
turtle.forward(8.0 * BIT_BOX / 2.0);
turtle.forward(16.0 * BIT_BOX / 2.0);
turtle.right(180.0);
draw_number(&mut turtle, NUMBER);
}
fn draw_text(turtle: &mut Turtle, text: &str) {
let mut row_num = 0;
for (char_num, (start, codepoint)) in text.char_indices().enumerate() {
println!("Character {}: {}", char_num, codepoint);
let byte_count = codepoint.len_utf8();
let row: &[u8] = &text.as_bytes()[start .. start + byte_count];
for byte in row {
println!(" Byte {:02}:\n Value: 0x{:02X}\n Bits: {:08b}", row_num, byte, byte);
let bits: &BitSlice<_, _> = byte.bits::<LittleEndian>();
draw_row(turtle, bits);
next_row(turtle, 90.0);
row_num += 1;
}
delimit(turtle, 8.0 * BIT_BOX - BIT_MARGIN);
}
}
fn draw_number(turtle: &mut Turtle, number: f64) {
let raw_number: u64 = number.to_bits();
let bits: &BitSlice<_, _> = raw_number.bits::<BigEndian>();
for (num, row) in bits.chunks(16).enumerate() {
println!("Row {} bits: {:b}", num, row);
draw_row(turtle, row);
next_row(turtle, -90.0);
}
}
fn draw_row<C, T>(turtle: &mut Turtle, row: &BitSlice<C, T>)
where C: Cursor, T: BitStore {
for &bit in row {
if bit {
turtle.set_pen_color("black");
}
else {
turtle.set_pen_color("light grey");
}
turtle.pen_down();
turtle.forward(BIT_WIDTH);
turtle.pen_up();
turtle.forward(BIT_MARGIN);
}
for _ in 0 .. row.len() {
turtle.backward(BIT_BOX);
}
}
fn delimit(turtle: &mut Turtle, width: f64) {
turtle.set_pen_color("grey");
turtle.pen_down();
turtle.forward(width);
turtle.backward(width);
next_row(turtle, 90.0);
}
fn next_row(turtle: &mut Turtle, angle: f64) {
turtle.pen_up();
turtle.left(angle);
turtle.forward(BIT_HEIGHT);
turtle.right(angle);
}