คู่มือแนะนำเกี่ยวกับรูปแบบโค้ด

รูปแบบโค้ด HIDL คล้ายกับโค้ด C++ ในเฟรมเวิร์ก Android โดยมีการเยื้อง 4 ช่องว่างและชื่อไฟล์แบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ผสมกัน การประกาศแพ็กเกจ การนำเข้า และ Docstring จะคล้ายกับใน Java โดยมีการแก้ไขเล็กน้อย

ตัวอย่างต่อไปนี้สำหรับ IFoo.hal และ types.hal แสดงรูปแบบโค้ด HIDL และมีลิงก์ด่วนไปยังรายละเอียดของแต่ละรูปแบบ (IFooClientCallback.hal, IBar.hal และ IBaz.hal ถูกละไว้)

hardware/interfaces/foo/1.0/IFoo.hal
/*
 * (License Notice)
 */

package android.hardware.foo@1.0;

import android.hardware.bar@1.0::IBar;

import IBaz;
import IFooClientCallback;

/**
 * IFoo is an interface that*/
interface IFoo {

    /**
     * This is a multiline docstring.
     *
     * @return result 0 if successful, nonzero otherwise.
     */
     foo() generates (FooStatus result);

    /**
     * Restart controller by power cycle.
     *
     * @param bar callback interface that* @return result 0 if successful, nonzero otherwise.
     */
    powerCycle(IBar bar) generates (FooStatus result);

    /** Single line docstring. */
    baz();


    /**
     * The bar function.
     *
     * @param clientCallback callback after function is called
     * @param baz related baz object
     * @param data input data blob
     */
    bar(IFooClientCallback clientCallback,
        IBaz baz,
        FooData data);

};
hardware/interfaces/foo/1.0/types.hal
/*
 * (License Notice)
 */

package android.hardware.foo@1.0;

/** Replied status. */
enum Status : int32_t {
    OK,
    /* invalid arguments */
    ERR_ARG,
    /* note, no transport related errors */
    ERR_UNKNOWN = -1,
};

struct ArgData {
    int32_t[20]  someArray;
    vec<uint8_t> data;
};

รูปแบบการตั้งชื่อ

ชื่อฟังก์ชัน ชื่อตัวแปร และชื่อไฟล์ควรสื่อความหมายชัดเจน และหลีกเลี่ยง การย่อคำมากเกินไป ถือว่าตัวย่อเป็นคำ (เช่น ใช้ INfc แทน INFC)

โครงสร้างไดเรกทอรีและการตั้งชื่อไฟล์

โครงสร้างไดเรกทอรีควรมีลักษณะดังนี้

  • ROOT-DIRECTORY
    • MODULE
      • SUBMODULE (ไม่บังคับ อาจมีมากกว่า 1 ระดับ)
        • VERSION
          • Android.mk
          • IINTERFACE_1.hal
          • IINTERFACE_2.hal
          • IINTERFACE_N.hal
          • types.hal (ไม่บังคับ)

สถานที่:

  • ROOT-DIRECTORY คือ
    • hardware/interfaces สำหรับแพ็กเกจ HIDL หลัก
    • vendor/VENDOR/interfaces สำหรับแพ็กเกจของผู้ให้บริการ โดย VENDOR หมายถึงผู้ให้บริการ SoC หรือ OEM/ODM
  • MODULE ควรเป็นคำเดียวที่เป็นตัวพิมพ์เล็กซึ่งอธิบาย ระบบย่อย (เช่น nfc) หากจำเป็นต้องใช้มากกว่า 1 คำ ให้ใช้ SUBMODULE ที่ซ้อนกัน โดยสามารถซ้อนกันได้มากกว่า 1 ระดับ
  • VERSION ควรเป็นเวอร์ชันเดียวกันทุกประการ (major.minor) ตามที่อธิบายไว้ในเวอร์ชัน
  • IINTERFACE_X ควรเป็นชื่ออินเทอร์เฟซที่มี UpperCamelCase/PascalCase (เช่น INfc) ตามที่อธิบายไว้ในชื่ออินเทอร์เฟซ

ตัวอย่าง

  • hardware/interfaces
    • nfc
      • 1.0
        • Android.mk
        • INfc.hal
        • INfcClientCallback.hal
        • types.hal

หมายเหตุ: ไฟล์ทั้งหมดต้องมีสิทธิ์แบบไม่สามารถเรียกใช้ได้ (ใน Git)

ชื่อแพ็กเกจ

ชื่อแพ็กเกจต้องใช้รูปแบบชื่อที่สมบูรณ์ (FQN) ต่อไปนี้ (เรียกว่า PACKAGE-NAME)

PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[]]]@VERSION

สถานที่:

  • PACKAGE คือแพ็กเกจที่แมปกับ ROOT-DIRECTORY โดยเฉพาะอย่างยิ่ง PACKAGE คือ
    • android.hardware สำหรับแพ็กเกจ HIDL หลัก (แมปกับ hardware/interfaces)
    • vendor.VENDOR.hardware สำหรับแพ็กเกจของผู้ให้บริการ โดยที่ VENDOR หมายถึงผู้ให้บริการ SoC หรือ OEM/ODM (การแมป กับ vendor/VENDOR/interfaces)
  • MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION เป็นชื่อโฟลเดอร์ที่ตรงกันทุกประการในโครงสร้างที่อธิบายไว้ใน โครงสร้างไดเรกทอรี
  • ชื่อแพ็กเกจควรเป็นตัวพิมพ์เล็ก หากยาวมากกว่า 1 คำ ควรใช้คำเหล่านั้นเป็นโมดูลย่อยหรือเขียนใน snake_case
  • โดยไม่ให้มีเว้นวรรค

ระบบจะใช้ FQN ในการประกาศแพ็กเกจเสมอ

เวอร์ชัน

เวอร์ชันควรมีรูปแบบดังนี้

MAJOR.MINOR

ทั้งเวอร์ชัน MAJOR และ MINOR ควรเป็นจำนวนเต็มเดียว HIDL ใช้กฎการกำหนดเวอร์ชัน เชิงความหมาย

การนำเข้า

การนำเข้ามี 1 ใน 3 รูปแบบต่อไปนี้

  • การนำเข้าทั้งแพ็กเกจ: import PACKAGE-NAME;
  • การนำเข้าบางส่วน: import PACKAGE-NAME::UDT; (หรือหากประเภทที่นำเข้าอยู่ในแพ็กเกจเดียวกันimport UDT;
  • การนำเข้าประเภทเท่านั้น: import PACKAGE-NAME::types;

PACKAGE-NAME เป็นไปตามรูปแบบในชื่อแพ็กเกจ ระบบจะนำเข้าแพ็กเกจปัจจุบัน types.hal (หากมี) โดยอัตโนมัติ (อย่านำเข้า อย่างชัดเจน)

ชื่อที่มีคุณสมบัติครบถ้วน (FQN)

ใช้ชื่อที่สมบูรณ์สำหรับการนำเข้าประเภทที่ผู้ใช้กำหนดเมื่อจำเป็นเท่านั้น ละเว้น PACKAGE-NAME หากประเภทการนำเข้าอยู่ในแพ็กเกจเดียวกัน FQN ต้องไม่มีการเว้นวรรค ตัวอย่างชื่อที่สมบูรณ์

android.hardware.nfc@1.0::INfcClientCallback

ในไฟล์อื่นภายใต้ android.hardware.nfc@1.0 โปรดดูอินเทอร์เฟซด้านบนเป็น INfcClientCallback มิฉะนั้น ให้ใช้เฉพาะชื่อที่ มีคุณสมบัติครบถ้วน

การจัดกลุ่มและการจัดลำดับการนำเข้า

ใช้บรรทัดว่างหลังการประกาศแพ็กเกจ (ก่อนการนำเข้า) การนำเข้าแต่ละรายการ ควรอยู่ในบรรทัดเดียวและไม่ควรมีการเยื้อง นำเข้ากลุ่มตามลำดับต่อไปนี้

  1. แพ็กเกจ android.hardware อื่นๆ (ใช้ชื่อที่สมบูรณ์ในตัวเอง)
  2. vendor.VENDOR แพ็กเกจอื่นๆ (ใช้ชื่อที่สมบูรณ์ในตัวเอง)
    • ผู้ให้บริการแต่ละรายควรเป็นกลุ่ม
    • จัดเรียงผู้ให้บริการตามลำดับตัวอักษร
  3. นำเข้าจากอินเทอร์เฟซอื่นๆ ในแพ็กเกจเดียวกัน (ใช้ชื่อที่เรียบง่าย)

เว้นบรรทัดว่างระหว่างกลุ่ม ภายในแต่ละกลุ่ม ให้จัดเรียงการนำเข้าตามตัวอักษร ตัวอย่าง

import android.hardware.nfc@1.0::INfc;
import android.hardware.nfc@1.0::INfcClientCallback;

/* Importing the whole module. */
import vendor.barvendor.bar@3.1;

import vendor.foovendor.foo@2.2::IFooBar;
import vendor.foovendor.foo@2.2::IFooFoo;

import IBar;
import IFoo;

ชื่ออินเทอร์เฟซ

ชื่ออินเทอร์เฟซต้องขึ้นต้นด้วย I ตามด้วยชื่อ UpperCamelCase/PascalCase ต้องกำหนดอินเทอร์เฟซที่มีชื่อ IFoo ในไฟล์ IFoo.hal ไฟล์นี้ มีได้เฉพาะคำจำกัดความสำหรับอินเทอร์เฟซ IFoo เท่านั้น (อินเทอร์เฟซ INAME ควรอยู่ใน INAME.hal )

ฟังก์ชัน

สำหรับชื่อฟังก์ชัน อาร์กิวเมนต์ และชื่อตัวแปรที่ส่งคืน ให้ใช้ lowerCamelCase ตัวอย่าง

open(INfcClientCallback clientCallback) generates (int32_t retVal);
oneway pingAlive(IFooCallback cb);

ชื่อฟิลด์ของโครงสร้างและสหภาพ

สำหรับชื่อฟิลด์ struct หรือ union ให้ใช้ lowerCamelCase ตัวอย่าง

struct FooReply {
    vec<uint8_t> replyData;
}

ชื่อประเภท

ชื่อประเภทหมายถึงคำจำกัดความของโครงสร้างหรือสหภาพ คำจำกัดความของประเภทการแจงนับ และ typedef สำหรับชื่อเหล่านี้ ให้ใช้ UpperCamelCase/PascalCase ตัวอย่างเช่น

enum NfcStatus : int32_t {
    /*...*/
};
struct NfcData {
    /*...*/
};

ค่า enum

ค่า Enum ควรเป็น UPPER_CASE_WITH_UNDERSCORES เมื่อส่งค่า enum เป็นอาร์กิวเมนต์ของฟังก์ชันและแสดงผลเป็นค่าที่ฟังก์ชันแสดงผล ให้ใช้ประเภท enum จริง (ไม่ใช่ประเภทจำนวนเต็มพื้นฐาน) ตัวอย่าง

enum NfcStatus : int32_t {
    HAL_NFC_STATUS_OK               = 0,
    HAL_NFC_STATUS_FAILED           = 1,
    HAL_NFC_STATUS_ERR_TRANSPORT    = 2,
    HAL_NFC_STATUS_ERR_CMD_TIMEOUT  = 3,
    HAL_NFC_STATUS_REFUSED          = 4
};

หมายเหตุ: ประเภทพื้นฐานของประเภท Enum จะประกาศอย่างชัดเจนหลังเครื่องหมายโคลอน การใช้ประเภท Enum จริงจะชัดเจนกว่าเนื่องจากไม่ได้ขึ้นอยู่กับคอมไพเลอร์

สำหรับชื่อที่สมบูรณ์ของค่า enum จะใช้โคลอน ระหว่างชื่อประเภท enum กับชื่อค่า enum

PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME

ชื่อที่สมบูรณ์ต้องไม่มีช่องว่าง ใช้ชื่อที่สมบูรณ์ เมื่อจำเป็นเท่านั้น และละเว้นส่วนที่ไม่จำเป็น ตัวอย่าง

android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK

ความคิดเห็น

สำหรับความคิดเห็นแบบบรรทัดเดียว //, /* */ และ /** */ ใช้ได้

// This is a single line comment
/* This is also single line comment */
/** This is documentation comment */
  • ใช้ /* */ สำหรับความคิดเห็น แม้ว่า HIDL จะรองรับ // สำหรับความคิดเห็น แต่เราไม่แนะนำให้ใช้เนื่องจากความคิดเห็นจะไม่ปรากฏในเอาต์พุตที่สร้างขึ้น
  • ใช้ /** */ สำหรับเอกสารที่สร้างขึ้น โดยจะใช้ได้กับ การประกาศประเภท เมธอด ฟิลด์ และค่า Enum เท่านั้น ตัวอย่าง
    /** Replied status */
    enum TeleportStatus {
        /** Object entirely teleported. */
        OK              = 0,
        /** Methods return this if teleportation is not completed. */
        ERROR_TELEPORT  = 1,
        /**
         * Teleportation could not be completed due to an object
         * obstructing the path.
         */
        ERROR_OBJECT    = 2,
        ...
    }
  • เริ่มความคิดเห็นหลายบรรทัดด้วย /** ในบรรทัดแยกกัน ใช้ * ที่จุดเริ่มต้นของแต่ละบรรทัด ปิดท้ายความคิดเห็นด้วย */ ในบรรทัดแยก โดยจัดตำแหน่งเครื่องหมายดอกจัน ตัวอย่าง
    /**
     * My multi-line
     * comment
     */
  • ประกาศการอนุญาตให้ใช้สิทธิและบันทึกการเปลี่ยนแปลงควรขึ้นบรรทัดใหม่ด้วย /* (เครื่องหมายดอกจันเดี่ยว) ใช้ * ที่จุดเริ่มต้นของแต่ละบรรทัด และวาง */ ในบรรทัดสุดท้ายด้วยตัวของมันเอง (เครื่องหมายดอกจันควรอยู่ในแนวเดียวกัน) ตัวอย่าง
    /*
     * Copyright (C) 2017 The Android Open Source Project
     * ...
     */
    
    /*
     * Changelog:
     * ...
     */

ส่งความคิดเห็น

เริ่มต้นแต่ละไฟล์ด้วยประกาศการอนุญาตให้ใช้สิทธิที่เหมาะสม สำหรับ HAL หลัก ควรเป็นใบอนุญาต Apache ของ AOSP ใน development/docs/copyright-templates/c.txt อย่าลืมอัปเดตปีและใช้/* */ความคิดเห็นหลายบรรทัดของสไตล์ ตามที่อธิบายไว้ข้างต้น

คุณเลือกเว้นบรรทัดว่างหลังประกาศเกี่ยวกับใบอนุญาตได้ ตามด้วย ข้อมูลบันทึกการเปลี่ยนแปลง/การควบคุมเวอร์ชัน ใช้ความคิดเห็นหลายบรรทัดในรูปแบบ /* */ ตามที่อธิบายไว้ข้างต้น วางบรรทัดว่างหลังบันทึกการเปลี่ยนแปลง แล้วตามด้วยการประกาศแพ็กเกจ

ความคิดเห็น TODO

รายการที่ต้องทำควรมีสตริง TODO เป็นตัวพิมพ์ใหญ่ทั้งหมด ตามด้วยเครื่องหมายโคลอน ตัวอย่าง

// TODO: remove this code before foo is checked in.

อนุญาตให้ใช้ความคิดเห็น TODO ในระหว่างการพัฒนาเท่านั้น และต้อง ไม่มีอยู่ในอินเทอร์เฟซที่เผยแพร่

ความคิดเห็นเกี่ยวกับอินเทอร์เฟซและฟังก์ชัน (docstring)

ใช้ /** */ สำหรับ Docstring แบบหลายบรรทัดและแบบบรรทัดเดียว อย่าใช้ // สำหรับ Docstring

Docstring สำหรับอินเทอร์เฟซควรอธิบายกลไกทั่วไปของอินเทอร์เฟซ เหตุผลในการออกแบบ วัตถุประสงค์ ฯลฯ Docstring สำหรับฟังก์ชันควรเฉพาะเจาะจงสำหรับฟังก์ชันนั้นๆ (เอกสารประกอบระดับแพ็กเกจจะอยู่ในไฟล์ README ในไดเรกทอรีแพ็กเกจ)

/**
 * IFooController is the controller for foos.
 */
interface IFooController {
    /**
     * Opens the controller.
     *
     * @return status HAL_FOO_OK if successful.
     */
    open() generates (FooStatus status);

    /** Close the controller. */
    close();
};

คุณต้องเพิ่ม @params และ @returns สำหรับแต่ละ พารามิเตอร์/ค่าที่ส่งคืน ดังนี้

  • @param ต้องเพิ่มสำหรับพารามิเตอร์แต่ละรายการ โดยควรตามด้วยชื่อพารามิเตอร์และสตริงเอกสาร
  • @return ต้องเพิ่มสำหรับค่าที่ส่งคืนแต่ละค่า ตามด้วยชื่อของค่าที่ส่งคืนและสตริงเอกสาร

ตัวอย่าง

/**
 * Explain what foo does.
 *
 * @param arg1 explain what arg1 is
 * @param arg2 explain what arg2 is
 * @return ret1 explain what ret1 is
 * @return ret2 explain what ret2 is
 */
foo(T arg1, T arg2) generates (S ret1, S ret2);

กฎการจัดรูปแบบ

กฎการจัดรูปแบบทั่วไปมีดังนี้

  • ความยาวของบรรทัด ข้อความแต่ละบรรทัดควรมีความยาวไม่เกิน 100 คอลัมน์
  • ช่องว่าง ไม่มีช่องว่างต่อท้ายในบรรทัด และบรรทัดว่าง ต้องไม่มีช่องว่าง
  • ช่องว่างเทียบกับแท็บ ใช้เฉพาะช่องว่าง
  • ขนาดการเยื้อง ใช้ช่องว่าง 4 ช่องสำหรับบล็อกและ 8 ช่องสำหรับบรรทัดที่ยาวเกินไป
  • การค้ำยัน ยกเว้นค่า คำอธิบายประกอบ วงเล็บปีกกาเปิดจะอยู่ในบรรทัดเดียวกับโค้ดที่อยู่ก่อนหน้า แต่วงเล็บปีกกาปิดและเครื่องหมายอัฒภาคที่ตามมาจะอยู่ใน ทั้งบรรทัด ตัวอย่าง
    interface INfc {
        close();
    };

การประกาศแพ็กเกจ

การประกาศแพ็กเกจควรอยู่ด้านบนของไฟล์หลังประกาศเกี่ยวกับใบอนุญาต ควรครอบครองทั้งบรรทัด และไม่ควรมีการเยื้อง โดยจะประกาศแพ็กเกจโดยใช้รูปแบบต่อไปนี้ (ดูการจัดรูปแบบชื่อได้ที่ชื่อแพ็กเกจ)

package PACKAGE-NAME;

ตัวอย่าง

package android.hardware.nfc@1.0;

การประกาศฟังก์ชัน

ชื่อฟังก์ชัน พารามิเตอร์ generates และค่าที่ส่งคืนควร อยู่ในบรรทัดเดียวกันหากพอ ตัวอย่าง

interface IFoo {
    /** ... */
    easyMethod(int32_t data) generates (int32_t result);
};

หากพารามิเตอร์และค่าที่ส่งคืนไม่พอที่จะอยู่ในบรรทัดเดียวกัน ให้พยายามวางพารามิเตอร์และค่าที่ส่งคืนในระดับการเยื้องเดียวกัน และแยกความแตกต่างของ generate เพื่อช่วย ให้ผู้อ่านเห็นพารามิเตอร์และค่าที่ส่งคืนได้อย่างรวดเร็ว ตัวอย่าง

interface IFoo {
    suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter,
                                          int32_t anotherVeryLongParameter);
    anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter,
                                             int32_t anotherVeryLongParameter)
                                  generates (int32_t theFirstReturnValue,
                                             int32_t anotherReturnValue);
    superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType(
            int32_t theFirstVeryLongParameter, // 8 spaces
            int32_t anotherVeryLongParameter
        ) generates (
            int32_t theFirstReturnValue,
            int32_t anotherReturnValue
        );
    /* method name is even shorter than 'generates' */
    foobar(AReallyReallyLongType aReallyReallyLongParameter,
           AReallyReallyLongType anotherReallyReallyLongParameter)
        generates (ASuperLongType aSuperLongReturnValue, // 4 spaces
                   ASuperLongType anotherSuperLongReturnValue);
}

รายละเอียดเพิ่มเติม:

  • วงเล็บเปิดจะอยู่บรรทัดเดียวกับชื่อฟังก์ชันเสมอ
  • โดยต้องไม่มีช่องว่างระหว่างชื่อฟังก์ชันกับวงเล็บเปิด
  • ไม่มีช่องว่างระหว่างวงเล็บและพารามิเตอร์ ยกเว้นเมื่อมีตัวขึ้นบรรทัดใหม่ระหว่างวงเล็บและพารามิเตอร์
  • หาก generates อยู่ในบรรทัดเดียวกับวงเล็บปิดก่อนหน้า ให้เว้นวรรคก่อนหน้า หาก generates อยู่ในบรรทัดเดียวกับวงเล็บเปิดถัดไป ให้เว้นวรรค
  • จัดแนวพารามิเตอร์และค่าที่ส่งคืนทั้งหมด (หากเป็นไปได้)
  • การเยื้องเริ่มต้นคือ 4 วรรค
  • พารามิเตอร์ที่ขึ้นบรรทัดใหม่จะจัดแนวให้ตรงกับพารามิเตอร์แรกในบรรทัดก่อนหน้า หรือมีการเยื้อง 8 ช่อง

คำอธิบายประกอบ

ใช้รูปแบบต่อไปนี้สำหรับคำอธิบายประกอบ

@annotate(keyword = value, keyword = {value, value, value})

จัดเรียงคำอธิบายประกอบตามลำดับตัวอักษรและเว้นวรรคหน้าและหลังเครื่องหมายเท่ากับ ตัวอย่าง

@callflow(key = value)
@entry
@exit

ตรวจสอบว่าคำอธิบายประกอบครอบคลุมทั้งบรรทัด ตัวอย่าง

/* Good */
@entry
@exit

/* Bad */
@entry @exit

หากคำอธิบายประกอบไม่พอในบรรทัดเดียวกัน ให้เยื้องโดยเว้น 8 ช่องว่าง ตัวอย่าง

@annotate(
        keyword = value,
        keyword = {
                value,
                value
        },
        keyword = value)

หากอาร์เรย์ค่าทั้งหมดไม่พอในบรรทัดเดียวกัน ให้ใส่การขึ้นบรรทัดใหม่หลังวงเล็บปีกกาเปิด { และหลังเครื่องหมายคอมมาแต่ละตัวในอาร์เรย์ ใส่วงเล็บปิด ต่อท้ายค่าสุดท้ายทันที อย่าใส่วงเล็บปีกกาหากมีค่าเพียงค่าเดียว

หากอาร์เรย์ค่าทั้งหมดพอดีในบรรทัดเดียวกัน ให้เว้นวรรคหลัง วงเล็บปีกกาเปิดและก่อนวงเล็บปีกกาปิด และเว้นวรรค 1 ครั้งหลังเครื่องหมายจุลภาคแต่ละตัว ตัวอย่าง

/* Good */
@callflow(key = {"val", "val"})

/* Bad */
@callflow(key = { "val","val" })

ต้องไม่มีบรรทัดว่างระหว่างคำอธิบายประกอบกับฟังก์ชัน การประกาศ ตัวอย่าง

/* Good */
@entry
foo();

/* Bad */
@entry

foo();

การประกาศ Enum

ใช้กฎต่อไปนี้สำหรับการประกาศ Enum

  • หากมีการแชร์การประกาศ enum กับแพ็กเกจอื่น ให้ใส่การประกาศ ใน types.hal แทนที่จะฝังไว้ภายในอินเทอร์เฟซ
  • ใช้การเว้นวรรคก่อนและหลังเครื่องหมายโคลอน และเว้นวรรคหลังประเภทพื้นฐาน ก่อนเครื่องหมายปีกกาเปิด
  • ค่า Enum สุดท้ายอาจไม่มีคอมมาเพิ่มเติม

การประกาศโครงสร้าง

ใช้กฎต่อไปนี้สำหรับการประกาศโครงสร้าง

  • หากมีการแชร์การประกาศโครงสร้างกับแพ็กเกจอื่น ให้ใส่การประกาศ ใน types.hal แทนที่จะฝังไว้ภายในอินเทอร์เฟซ
  • เว้นวรรคหลังชื่อประเภท struct ก่อนเครื่องหมายปีกกาเปิด
  • จัดแนวชื่อฟิลด์ (ไม่บังคับ) ตัวอย่าง
    struct MyStruct {
        vec<uint8_t>   data;
        int32_t        someInt;
    }

การประกาศอาร์เรย์

อย่าเว้นวรรคระหว่างรายการต่อไปนี้

  • ประเภทองค์ประกอบและวงเล็บเหลี่ยมเปิด
  • วงเล็บเหลี่ยมเปิดและขนาดอาร์เรย์
  • ขนาดอาร์เรย์และวงเล็บเหลี่ยมปิด
  • วงเล็บเหลี่ยมปิดและวงเล็บเหลี่ยมเปิดถัดไป หากมีมิติข้อมูลมากกว่า 1 รายการ

ตัวอย่าง

/* Good */
int32_t[5] array;

/* Good */
int32_t[5][6] multiDimArray;

/* Bad */
int32_t [ 5 ] [ 6 ] array;

เวกเตอร์

อย่าเว้นวรรคระหว่างรายการต่อไปนี้

  • vec และวงเล็บสามเหลี่ยมเปิด
  • วงเล็บเหลี่ยมเปิดและประเภทองค์ประกอบ (ข้อยกเว้น: ประเภทองค์ประกอบยังเป็น vec)
  • ประเภทองค์ประกอบและวงเล็บปีกกาปิด (ข้อยกเว้น: ประเภทองค์ประกอบยังเป็น vec)

ตัวอย่าง

/* Good */
vec<int32_t> array;

/* Good */
vec<vec<int32_t>> array;

/* Good */
vec< vec<int32_t> > array;

/* Bad */
vec < int32_t > array;

/* Bad */
vec < vec < int32_t > > array;