type String { 
    length uint32,
    data [u8; length],
}

// needs three bits to store this
@exhaustive
enum LogLevel {
    Error = 0,
    Warn = 1,
    Info = 2,
    Debug = 3,
    Trace = 4,
}

type LogMessage {
    log_level = LogLevel,
    log_message = String,
}



// This is displayed as bits sent over the wire 
[
    010 // INFO 
    00000000_00000000_00000000_00000011 // Length of the string
    01001000 // H
    01101001 // i
    00100001 // !
]

// This is displayed as bytes in memory 
[
    0x3 // INFO 
    0xD // Length of the string
    0x48
    0x69
    0x21
]





enum LogResult {
    Ok,
    Error,
}

@exhaustive
protocol Logger {

    fn log(LogMessage) -> LogResult;
    
    fn error(String) -> LogResult;
    fn warn(String) -> LogResult;
    fn info(String) -> LogResult;
    fn debug(String) -> LogResult;
    fn trace(String) -> LogResult;

    fn flush() -> LogResult;
}
TODO argue about time being added after the fact in the logger or inplace by the loggee