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: parse_models.rs
    path of file: ./repos/prisma-engines/query-engine/connector-test-kit-rs/query-tests-setup/src/templating
    
    the code of the file until where you have to start completion: use super::*;
use itertools::Itertools;
use std::fmt::Display;

/// A datamodel fragment is the parsed version of a `#<ident>(...)` template string.
#[derive(Debug, PartialEq)]
pub enum DatamodelFragment {
    Id(IdFragment),
    M2m(M2mFragment),
}

impl DatamodelFragment {
    pub fn parse(ident: &str, args: Vec<FragmentArgument>) -> TemplatingResult<Self> {
    
    
    fn from_args(args: Vec<FragmentArgument>) -> TemplatingResult<Self> {
        if args.len() < 4 {
            return Err(TemplatingError::num_args("m2m", 4, args.len()));
        }

        let mut args = args.into_iter();
        let (field_name, field_type) = args.next_tuple().unwrap();
        let (opposing_name, opposing_type) = args.next_tuple().unwrap();
        let relation_name = args.next().map(|v| v.into_value_string().unwrap());

        let field_name = field_name.into_value_string()?;
        let field_type = field_type.into_value_string()?;
        let opposing_name = opposing_name.into_value_string()?;
        let opposing_type = opposing_type.into_value_string()?;

        Ok(Self {
            field_name,
            field_type,
            opposing_name,
            opposing_type,
            relation_name,
        })
    }