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: float.rs
    path of file: ./repos/readyset/readyset-data/src
    
    the code of the file until where you have to start completion: use std::convert::TryInto;

use readyset_errors::{ReadySetError, ReadySetResult};
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;

use crate::{r#enum, DfType, DfValue};

fn coerce_f64_to_int<I>(val: f64) -> Option<I>
where
    i64: TryInto<I>,
{
    if -0.5 < val && val < 0.5 {
        return 0.try_into().ok();
    }

    if val <= i64::MIN as f64 - 0.5 || val >= i64::MAX as f64 + 0.5 {
        return None;
    }

    (val.round() as i64).try_into().ok()
}

fn coerce_f64_to_uint<I>(val: f64) -> Option<I>
where
    u64: TryInto<I>,
{
    if -0.5 < val && val < 0.5 {
        return 0.try_into().ok();
    }

    if val <= -0.5 || val >= u64::MAX as f64 + 0.5 {
        return None;
    }

    (val.round() as u64).try_into().ok()
}

pub(crate) fn coerce_f64(val: f64, to_ty: &DfType, from_ty: &DfType) -> ReadySetResult<DfValue> {
    let err = |deets: &str| ReadySetError::DfValueConversionError {
        src_type: "Double".to_string(),
        target_type: to_ty.to_string(),
        details: deets.to_string(),
    };

    let bounds_err = || err("out of bounds");

    if val.is_infinite() {
        return Err(err("Â±inf not allowed"));
    }

    if val.is_nan() {
        return Err(err("Nan not allowed"));
    }

    match *to_ty {
        DfType::Bool => Ok(DfValue::from(val != 0.0)),

        DfType::Double => Ok(DfValue::Double(val)),

        DfType::Float => {
            let val = val as f32;
            if val.is_infinite() {
                return Err(bounds_err());
            }
            Ok(DfValue::Float(val))
        }

        DfType::Numeric { .. } => Decimal::from_f64_retain(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),

        DfType::TinyInt => coerce_f64_to_int::<i8>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedTinyInt => coerce_f64_to_uint::<u8>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::SmallInt => coerce_f64_to_int::<i16>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedSmallInt => coerce_f64_to_uint::<u16>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::Int => coerce_f64_to_int::<i32>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedInt => coerce_f64_to_uint::<u32>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::BigInt => coerce_f64_to_int::<i64>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedBigInt => coerce_f64_to_uint::<u64>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),

        // The numeric cast from f64 to usize will round down, which is what we want for enums:
        DfType::Enum { ref variants, .. } => {
            Ok(r#enum::apply_enum_limits(val as usize, variants).into())
        }

        DfType::Text(collation) => Ok(DfValue::from_str_and_collation(&val.to_string(), collation)),

        DfType::VarChar(l, ..) => {
            let mut val = val.to_string();
            val.truncate(l as usize);
            Ok(val.to_string().into())
        }

        
    
pub(crate) fn coerce_f64(val: f64, to_ty: &DfType, from_ty: &DfType) -> ReadySetResult<DfValue> {
    let err = |deets: &str| ReadySetError::DfValueConversionError {
        src_type: "Double".to_string(),
        target_type: to_ty.to_string(),
        details: deets.to_string(),
    };

    let bounds_err = || err("out of bounds");

    if val.is_infinite() {
        return Err(err("Â±inf not allowed"));
    }

    if val.is_nan() {
        return Err(err("Nan not allowed"));
    }

    match *to_ty {
        DfType::Bool => Ok(DfValue::from(val != 0.0)),

        DfType::Double => Ok(DfValue::Double(val)),

        DfType::Float => {
            let val = val as f32;
            if val.is_infinite() {
                return Err(bounds_err());
            }
            Ok(DfValue::Float(val))
        }

        DfType::Numeric { .. } => Decimal::from_f64_retain(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),

        DfType::TinyInt => coerce_f64_to_int::<i8>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedTinyInt => coerce_f64_to_uint::<u8>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::SmallInt => coerce_f64_to_int::<i16>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedSmallInt => coerce_f64_to_uint::<u16>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::Int => coerce_f64_to_int::<i32>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedInt => coerce_f64_to_uint::<u32>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::BigInt => coerce_f64_to_int::<i64>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),
        DfType::UnsignedBigInt => coerce_f64_to_uint::<u64>(val)
            .ok_or_else(bounds_err)
            .map(DfValue::from),

        // The numeric cast from f64 to usize will round down, which is what we want for enums:
        DfType::Enum { ref variants, .. } => {
            Ok(r#enum::apply_enum_limits(val as usize, variants).into())
        }

        DfType::Text(collation) => Ok(DfValue::from_str_and_collation(&val.to_string(), collation)),

        DfType::VarChar(l, ..) => {
            let mut val = val.to_string();
            val.truncate(l as usize);
            Ok(val.to_string().into())
        }

        DfType::Char(l, ..) => {
            let mut val = val.to_string();
            val.truncate(l as usize);
            val.extend(std::iter::repeat(' ').take((l as usize).saturating_sub(val.len())));
            Ok(val.into())
        }

        DfType::Blob => Ok(DfValue::ByteArray(val.to_string().into_bytes().into())),

        DfType::VarBinary(l) => {
            let mut val = val.to_string();
            val.truncate(l as usize);
            Ok(val.to_string().into_bytes().into())
        }

        DfType::Binary(l) => {
            let mut val = val.to_string();
            val.truncate(l as usize);
            val.extend(std::iter::repeat(' ').take((l as usize).saturating_sub(val.len())));
            Ok(val.into_bytes().into())
        }

        DfType::Json | DfType::Jsonb => Ok(val.to_string().into()),

        DfType::Time { .. } => {
            // https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html
            // As a number in hhmmss format, provided that it makes sense as a time. For
            // example, 101112 is understood as '10:11:12'. The following
            // alternative formats are also understood: ss, mmss, or hhmmss.
            let ms = (val.fract() * 1000000.0).round() as u64;
            let val = val.trunc() as u64;
            let hh = val / 1_00_00;
            let mm = val / 1_00 % 1_00;
            let ss = val % 1_00;
            Ok(mysql_time::MySqlTime::from_hmsus(true, hh as _, mm as _, ss as _, ms).into())
        }

        DfType::Date
        | DfType::DateTime { .. }
        | DfType::Timestamp { .. }
        | DfType::TimestampTz { .. } => crate::integer::coerce_integer(
            coerce_f64_to_int::<i64>(val).ok_or_else(bounds_err)?,
            to_ty,
            from_ty,
        ),

        DfType::Unknown
        | DfType::MacAddr
        | DfType::Inet
        | DfType::Uuid
        | DfType::Bit(_)
        | DfType::VarBit(_)
        | DfType::Array(_) => Err(err("not allowed")),
    }
}