While the code below is an early prototype and not to be taken too seriously concerning how I implement protocol buffers at this stage, I fail to understand what the error message rust compilers blesses me with refers to.
src\main.rs:89:9: 89:36 error: type mismatch resolving
for<'r> <[closure src\ma in.rs:75:33: 88:10] as core::ops::FnOnce<(u32, gpb::definitions::WireType, &'r collections::vec::Vec<u8>, usize)>>::Output == usize
: expected bound lifetime parameter , found concrete lifetime [E0271] src\main.rs:89 gpb::decoding::read_message( source, field_handler );
Even after reading the 3 documentation chapters on lifetimes et. al. I did not come across the term "concrete lifetime" and thus have trouble figuring out what code this error relates to. The closure itself, one or multiple arguments, the return code? The passing of the closure to read_message()
? ...
main.rs snippet
fn from_gpb( source : &Vec<u8>) -> TimeMessage {
fn init_vec_u64( count : usize, init_value : u64) -> Vec<u64> {
let mut result = Vec::<u64>::with_capacity(count);
for i in 0..count {
result.push(init_value);
}
result
}
let mut message_id : u32 = 0;
let mut times_sec = init_vec_u64(4,0u64);
let mut times_usec = init_vec_u64(4,0u64);
let mut max_time_index = 0;
let mut time_index = | index | { if max_time_index < index { max_time_index = index;}};
let mut field_handler = |tag,wire_type,source,position| -> usize {
match (tag,wire_type) {
(1u32,gpb::definitions::WireType::Varint) => {let (v,p) = gpb::decoding::read_varint32(source,position); message_id = v; p},
(2u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[0] = sec; time_index(0); p},
(3u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[0] = usec; time_index(0); p},
(4u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[1] = sec; time_index(1);p},
(5u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[1] = usec; time_index(1);p},
(6u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[2] = sec; time_index(2);p},
(7u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[2] = usec; time_index(2); p},
(8u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[3] = sec; time_index(3); p},
(9u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[3] = usec; time_index(3); p},
(_,_) => panic!("Invalid field tag/wire_type combination!") // TODO: change the panic to a gpb::decoding::skip(..) call.
}
};
gpb::decoding::read_message( source, field_handler );
let mut make_times = || -> Vec<prectime::PrecTime> {
let time_count = max_time_index+1;
let mut times = Vec::<prectime::PrecTime>::with_capacity(time_count);
times_sec.truncate(time_count);
times_usec.truncate(time_count);
for i in 0..time_count {
times.push(prectime::PrecTime { sec : times_sec[i], usec : times_usec[i]});
}
times
};
TimeMessage { id : message_id, times : make_times() }
}
gpb.rs snippet
pub fn read_message<F>( source : &Vec<u8>, field_handler : F) where F: Fn(u32,super::definitions::WireType, &Vec<u8>, usize) -> usize {
let mut cursor = 0;
while cursor < source.len() {
let (tag_and_wire_type, position) = read_varint32( source, cursor );
let wt = super::definitions::wire_type_from_value( tag_and_wire_type & 0x07u32 );
let tag = (tag_and_wire_type >> 3);
let new_pos = field_handler(tag,wt, source,position);
cursor = new_pos;
}
}
Summary of what the code does:
- define field_handler function
- read_message(data,field_handler) -> calls n times: field_handler
- exit scope.
As anything (the closure, the calls, the vectors, the field_handler writes in from_gpb()
context,...) is defined inside from_gpb()
function, I simply do not understand how the lifetime could become an issue. All information about lifetimes should be available to the compiler.