You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: id.rs
    path of file: ./repos/rustix/src/process
    
    the code of the file until where you have to start completion: //! Unix user, group, and process identifiers.
//!
//! # Safety
//!
//! The `Uid`, `Gid`, and `Pid` types can be constructed from raw integers,
//! which is marked unsafe because actual OS's assign special meaning to some
//! integer values.
#![allow(unsafe_code)]

use crate::{backend, io};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(linux_kernel)]
use backend::process::types::RawCpuid;

/// The raw integer value of a Unix user ID.
pub use crate::ugid::RawUid;

/// The raw integer value of a Unix group ID.
pub use crate::ugid::RawGid;

/// The raw integer value of a Unix process ID.
pub use crate::pid::RawPid;

pub u
    
pub fn getgroups() -> io::Result<Vec<Gid>> {
    // This code would benefit from having a better way to read into
    // uninitialized memory, but that requires `unsafe`.
    let mut buffer = Vec::with_capacity(8);
    buffer.resize(buffer.capacity(), Gid::ROOT);

    loop {
        let ngroups = backend::process::syscalls::getgroups(&mut buffer)?;

        let ngroups = ngroups as usize;
        assert!(ngroups <= buffer.len());
        if ngroups < buffer.len() {
            buffer.resize(ngroups, Gid::ROOT);
            return Ok(buffer);
        }
        // Use `Vec` reallocation strategy to grow capacity exponentially.
        buffer.reserve(1);
        buffer.resize(buffer.capacity(), Gid::ROOT);
    }
}