Idiomatic way to represent a keyboard layout

I'm trying to represent a keyboard layout (abstractly, a mapping from keys to characters on some keyboard) in Rust. I want to be able to easily access individual keys as well as rows and columns.

This is the sort of data type I'm looking for. This would represent a keyboard layout on a keyboard with four keys arranged in two rows/two columns.

struct Keyboard<'a> {
    key_top_left: char,
    key_top_right: char,
    key_bottom_left: char,
    key_bottom_right: char,

    row_1: [&'a char; 2],
    row_2: [&'a char; 2],
}

Honestly, I don't understand what the lifetime parameter does, but I needed it to avoid errors. The problem is, I don't even know how to initialize an instance of this struct so that row_1 contains pointers to self.key_top_left and self.key_top_right.

Is there a clean way to initialize this struct? Is there a better approach?

You cannot have references into the same struct.

Why do you want a reference to the other chars?

@alice Thanks, that clears things up. The idea is that I'll want to iterate over specific rows, check the keys adjacent to a given key, etc.

One way to implement this would be to store the rows and then provide getters/setters for "named' keys.

struct Keyboard {
  row_1: [char; 2],
  row_2: [char; 2],
}

impl Keyboard {
  pub fn top_left(&self) -> char {
    self.row_1[0]
  }
 
  pub fn set_top_left(&mut self, value: char) {
    self.row_1[0] = value;
  }

  ...
}

Or, alternatively:

enum Keys {
    KeyTopLeft = 0,
    KeyTopRight = 1,
    KeyBottomRight = 2,
    KeyBottomLeft = 3,
}

struct Keyboard {
  keys: [char; 4],
}
impl Keyboard {
    pub fn get_row(&self, row: usize) -> &[char] {
        self.keys[2*row..2*(row+1)]
    }
    pub fn get_key(&self, key: Keys) -> char {
        self.keys[key as usize]
    }
}