Goal

Today I will continue on implementing credentials. I have most of the obnam credential openpgp-soft command implemented, but I ran into the problem that it's not of the type that the Store wants to put it in the store.

Plan

Rather than forcing myself forward, I'll take a step to the side. I'll refactor things so that the store abstraction deals in a new type, "chunk in the store", so that normal chunks, client chunks, and credential chunks can all be converted to that.

Notes

  • I can implement StoreChunnh as a type or as a trait. I'll start by implementing it as a type, because that feels easier. I can refactor that later if need be. For now I don't expect to be able to store arbitrary data in the store, so the flexibility of a trait doesn't seem necessary.
  • Actually, no, I think a trait might be useful for dealing with fake chunks for tests. I'll implement a trait.
  • The trait needs to define methods for getting metadata for the chunk, and to serialize it to bytes, and deserializing it from bytes. This is what the store needs to store and retrieve a chunk.
pub trait StoreChunk<'a>: Serialize + Deserialize<'a> {
    const COOKIE: &str;
    fn metadata(&self) -> &Metadata;
}
  • I can let the type that implements the trait cope with serialization or deserialization, or I have the store do this. I think it makes sense to avoid having each type have to implement it.
  • However, that means the type needs to specify the cookie to use.
  • Upon consideration, I'll name the trait Storable.
  • While implementing deserialization in Store, I run into an interesting lifetime problem. The Store::get_chunk method reads a file to a temporary buffer, then parses that with postcard::from_bytes. That function declares that is output has the same lifetime as its input. That's reasonable. But in this case the output is a Chunk that doesn't store any data from or reference to the temporary buffer. It makes a copy.
  • I can use the static life time in the Storable trait, for Deserializer. That means, at least, that an implementer of the trait doesn't need to declare lifetimes, which is a little simpler.
  • But that doesn't solve the problem: the lifetime of the parsed chunk still exceeds that of the temporary buffer.
  • If Storable has a lifetime different from Deserialize, that'll work. No it doesn't, because deserialized chunk still has a lifetime that has to be at most that of the temporary array.
  • Cloning the parse result doesn't help, because the type parameter still has the lifetime that makes the compiler think the type has specific lifetime, and I think the clone carries that over.
  • I can get around this by changing the trait to have a parse constructor function. But not today, I've run out of time.

Summary

Made no progress at all, except in understanding the solution space. I'll have to think about what to do, next time.

Comments?

If you have feedback on this development session, please use the following fediverse thread: https://toot.liw.fi/@liw/114923908810561244.