برنامه نویسی

جاسازی KCL در Rust – Dev Community

KCL چیست؟

KCL یک زبان پیکربندی جدید و جالب است.
کمی شبیه مخلوطی از yaml و hcl است.

# This is a KCL document

title = "KCL Example"

owner = {
    name = "The KCL Authors"
    date = "2020-01-02T03:04:05"
}

database = {
    enabled = True
    ports = [8000, 8001, 8002]
    data = [["delta", "phi"], [3.14]]
    temp_targets = {cpu = 79.5, case = 72.0}
}

servers = [
    {ip = "10.0.0.1", role = "frontend"}
    {ip = "10.0.0.2", role = "backend"}
]
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اما آنچه در جدول به ارمغان می آورد این است که KCL اضافه کردن تایپ و اعتبار داده به پیکربندی شما را اضافه می کند.

اعتبار سنجی و تایپ می تواند از طریق داده های شما اعمال شود schemaبشر

schema User:
    name: str
    age: int
    message?: str
    data: Data
    labels: {str:}
    hc: [int]

    check:
        age > 10, "age must > 10"

schema Data:
    id: int
    value: int = 9000
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با schema ما می توانیم تعریف کنیم که کدام قسمت ها نوع خاصی از داده ها باید داشته باشند.
علاوه بر این ما می توانیم انواع اضافه کنیم ، مقادیر پیش فرض را تنظیم کنیم و حتی از طریق محدودیت ها را در قسمت ها اعمال کنیم checkبشر

بعد از تعریف ، الف schema می تواند فوری شود

User {
  name = "Foo"
  age = 42
  data = Data {
    id = 0
  }
  labels = {
    bar = 12
    baz = "some label"
  }
  hc = [1,2,3]
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سپس کد KCL را می توان در JSON یا YAML استاندارد “گردآوری کرد”.
قطعه کد کاربر از بالا “کامپایل” به:

{
  "name": "Foo",
  "age": 42,
  "data": {
    "id": 0,
    "value": 9000
  },
  "labels": {
    "bar": 12,
    "baz": "some label"
  },
  "hc": [
    1,
    2,
    3
  ]
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

یا

name: Foo
age: 42
data:
  id: 0
  value: 9000
labels:
  bar: 12
  baz: some label
hc:
- 1
- 2
- 3
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

KCL ویژگی های جالب تری دارد ، مانند جریان کنترل ، ماژول ها و حتی رجیستری برای این ماژول ها ، به طوری که می توان طرحواره ها را به راحتی به اشتراک گذاشته و دوباره استفاده کرد.
اما اگر می خواهید اطلاعات بیشتری در مورد KCL داشته باشید ، فقط به KCL-lang.io مراجعه کنید ، باید به عنوان یک مقدمه KCL کافی باشد.

جاسازی KCL در زنگ زدگی

پس از فهمیدن اینکه خود KCL در Rust نوشته شده است (در بیشتر مثالها KCL را به عنوان یک ابزار CLI می بینید) ، من تصمیم گرفتم که این یک ایده جالب باشد که KCL را در برنامه Rust خود جاسازی کنم تا بتوانید پرونده پیکربندی برنامه را تأیید کنید.

خوشبختانه ، KCL دارای lib که چندین زبان را ارائه می دهد و به راحتی از طریق می توان اضافه کرد:

cargo add --git https://github.com/kcl-lang/lib kcl-lang
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

پس از آن ، می توانید KCL را در کد زنگ خود مانند این کامپایل کنید:

let api = API::default();
let args = &ExecProgramArgs {
    k_filename_list: vec!["main.k".to_string()],
    k_code_list: vec!["a = 1".to_string()],
    ..Default::default()
};
let exec_result = api.exec_program(args)?;
println!("{}", exec_result.yaml_result);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

من فرض می کنم این CLI API است ، زیرا ما باید اضافه کنیم لیست پرونده ها (آنها هیچ ارتباطی برای این مورد استفاده ندارند ، اما شما نمی توانید آنها را پرش کنید) و خروجی stdout & stderr را که CLI با آن تولید می کند دریافت کنید exec_resultبشر

ایده این بود که طرح پیکربندی را به کد منبع اضافه کرده و آن را در طول زمان کامپایل از طریق include_str!() کلان

طرحواره اینگونه به نظر می رسد:

# schema.k
schema Configuration:
  api: API = API {}
  gateway: Gateway = Gateway {}

schema API:
  port: int = 8150
  check:
    1 <= port <= 65535, "API Port not in range 1 to 65535"

schema Gateway:
  port: int = 80
  check:
    1 <= port <= 65535, "Gatewayport Port not in range 1 to 65535"
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ساختار زنگ زدگی مربوطه:

#[derive(Debug, Serialize, Deserialize)]
pub struct Configuration {
    pub api: APIConfiguration,
    pub gateway: GatewayConfiguration,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct APIConfiguration {
    pub port: u16,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct GatewayConfiguration {
    pub port: u16,
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

من قصد داشتم کاربران را قادر به نوشتن فایل پیکربندی خود در KCL مانند:

# Long version
api = {
  port = 8150
}
# Short version
gateway.port = 8080
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سپس آن پرونده پیکربندی را در برابر طرح پیکربندی من که شامل تمام مقادیر پیش فرض لازم است ، کامپایل کنید.

بنابراین من می خواهم محتوای پرونده پیکربندی کاربر را با تعریف طرحواره خود با موارد زیر ترکیب کنم:

# schema.k content
schema Configuration:
  api: API = API {}
  gateway: Gateway = Gateway {}

schema API:
  port: int = 8150
  check:
    1 <= port <= 65535, "API Port not in range 1 to 65535"

schema Gateway:
  port: int = 80
  check:
    1 <= port <= 65535, "Gatewayport Port not in range 1 to 65535"

Configuration {
  # User configuration file content
  api = {
    port = 8150
  }
  gateway.port = 8080
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و سرانجام ، کد زنگ زدگی لازم برای رها کردن ساختار پیکربندی از کد KCL کامپایل شده:

impl Configuration {
    pub fn default() -> Result<Self> {
        Self::process_kcl(None)
    }

    pub fn from_configuration_file(path: &Path) -> Result<Self> {
        Self::process_kcl(Some(path))
    }

    fn process_kcl(path: Option<&Path>) -> Result<Self> {
        let mut file_name = "default-configuration.k".to_string();
        let mut code = String::new();
        if let Some(path) = path {
            file_name = "configuration.k".to_string();
            code = std::fs::read_to_string(path)?;
        }
        let code = format!("{}\nConfiguration{{\n{}}}", SCHEMA, code);
        let args = &ExecProgramArgs {
            k_filename_list: vec![file_name],
            k_code_list: vec![code],
            ..Default::default()
        };
        let api = API::default();
        let exec_result = api.exec_program(args)?;
        if !exec_result.err_message.is_empty() {
            return Err(anyhow!(
                "Configuration error:\n\n{}",
                exec_result.err_message
            ));
        }
        serde_json::from_str(&exec_result.json_result)
          .map_err(|err| anyhow!(err))
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بدون ارائه پرونده پیکربندی ، ما در برابر a کامپایل می کنیم Configuration{} به عنوان مثال ، که سپس تمام مقادیر پیش فرض را از طرح دریافت می کند.

کمی عجیب به نظر می رسد که اگر در برابر برخی از پیکربندی های کاربر که برای طرح ارائه شده معتبر نیست ، نتیجه خطا دریافت نمی کنیم.

تنها راه برای بررسی خطای تلفیقی بررسی اینکه آیا exec_result.err_message است ، ""بشر این پیام خطا خروجی STDERR است که در صورت عدم موفقیت ، ابزار CLI تولید می کند.
دست و پا گیر است ، اما حداقل ما با اطلاعات خاص در مورد آنچه در کد پیکربندی KCL اشتباه است ، پیام خطای خوبی دریافت می کنیم.

مرحله آخر پس از آن برای رها کردن Configuration ساختار از نمایش JSON از نتیجه تلفیقی -> ما می توانیم برنامه زنگ زدگی خود را از طریق پرونده پیکربندی KCL پیکربندی کنیم.

مرحله آخر پس از آن برای رها کردن Configuration ساختار از نمایش JSON از نتیجه تلفیقی -> ما می توانیم برنامه زنگ زدگی خود را از طریق پرونده پیکربندی KCL پیکربندی کنیم.

پایان

اول فکر: این کار می کند و این یک چیز خوب است!

فکر دوم: کار با CLI API در کد زنگ زدگی به نوعی بی دست و پا است و پس از آن ، مجدداً ساختار ساختار را از نمایندگی JSON یا YAML غیر ضروری به نظر می رسد.
من مطمئن هستم که یک روش باهوش تر برای تجزیه مستقیم KCL و ایجاد ساختار با مقادیر Serde که توسط تجزیه کننده تولید می شود وجود دارد.
متأسفانه مستندات KCL-Lang Lib بسیار کوتاه نگه داشته می شود و من نتوانستم رویکردی مانند آن پیدا کنم.

در مورد یک کلان رویه ای چطور؟

تمام آن کد دیگ بخار نیز می تواند توسط یک کلان رویه ای که برای آن اعمال می شود تولید شود Configuration ساختار ، شبیه به آنچه به عنوان مثال Serde ، Clap و غیره انجام می شود.

با این وجود ، KCL جالب است

به نظر من پیکربندی KCL یک مکمل عالی برای زنگ زدگی است.
مشابه زنگ زدگی ، KCL از انواع و محدودیت ها استفاده می کند تا احتمال نادرست پیکربندی ما به حداقل برسد.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا