Complete Core
Some checks failed
CI / build-linux-and-wasm (x64-linux) (push) Has been cancelled

This commit is contained in:
2026-01-25 18:26:59 +05:30
parent cfa0759133
commit 601b573983
51 changed files with 2110 additions and 4778 deletions

313
Docs/CODING-STYLE.md Normal file
View File

@ -0,0 +1,313 @@
# **IACore - C++ Style Guide**
This document defines the coding standards for IACore and all IA Projects.
Philosophy: Enforce Rust-like memory safety and discipline within modern C++20.
---
### **1. Oxide Usage**
Usage of [`Oxide`](https://github.com/I-A-S/Oxide) library and its philosophy is mandatory.
`Oxide` is a single header library and a truncated version of it is listed below.
```cpp
#define OX_UNUSED(v) (void)(v)
namespace Oxide {
// =============================================================================
// Primitive Types
// =============================================================================
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using f32 = float;
using f64 = double;
using usize = std::size_t;
using isize = std::ptrdiff_t;
// =============================================================================
// Template Types
// =============================================================================
template <typename T> using Const = const T;
template <typename T> using Mut = T;
template <typename T> using Ref = const T &;
template <typename T> using MutRef = T &;
template <typename T> using ForwardRef = T &&;
// =============================================================================
// Memory & Ownership
// =============================================================================
template <typename T> using Box = std::unique_ptr<T>;
template <typename T> using Arc = std::shared_ptr<T>;
template <typename T> using Weak = std::weak_ptr<T>;
template <typename T, typename... Args>
[[nodiscard]] inline auto make_box(ForwardRef<Args>... args) -> Box<T> {
return std::make_unique<T>(std::forward<Args>(args)...);
}
template <typename T, typename... Args>
[[nodiscard]] inline auto make_arc(ForwardRef<Args>... args) -> Arc<T> {
return std::make_shared<T>(std::forward<Args>(args)...);
}
// =============================================================================
// Error Handling
// =============================================================================
template <typename T, typename E = std::string>
using Result = Oxide::Internal::Expected<T, E>;
template <typename E> [[nodiscard]] inline auto fail(ForwardRef<E> error) {
return Oxide::Internal::make_unexpected(std::forward<E>(error));
}
template <typename... Args>
[[nodiscard]] inline auto fail(Ref<std::format_string<Args...>> fmt,
ForwardRef<Args>... args) {
return Oxide::Internal::make_unexpected(
std::format(fmt, std::forward<Args>(args)...));
}
// =============================================================================
// Utilities
// =============================================================================
namespace Env {
#if defined(NDEBUG)
constexpr Const<bool> IS_DEBUG = false;
constexpr Const<bool> IS_RELEASE = true;
#else
constexpr Const<bool> IS_DEBUG = true;
constexpr Const<bool> IS_RELEASE = false;
#endif
} // namespace Env
[[noreturn]] inline void
panic(Ref<std::string> msg,
Ref<std::source_location> loc = std::source_location::current()) {
std::cerr << "\n[panic] " << msg << "\n At: " << loc.file_name()
<< ":" << loc.line() << "\n";
std::abort();
}
inline void
ensure(Const<bool> condition, Ref<std::string> msg,
Ref<std::source_location> loc = std::source_location::current()) {
if (Env::IS_DEBUG && !condition) {
std::cerr << "\n[assert] " << msg << "\n At: " << loc.file_name()
<< ":" << loc.line() << "\n";
std::abort();
}
}
using String = std::string;
using StringView = std::string_view;
template <typename T> using Option = std::optional<T>;
template <typename T> using Vec = std::vector<T>;
template <typename T> using Span = std::span<T>;
template <typename T1, typename T2> using Pair = std::pair<T1, T2>;
template <typename T, usize Count> using Array = std::array<T, Count>;
} // namespace Oxide
#define OX_TRY_PURE(expr) \
{ \
auto _ox_res = (expr); \
if (!_ox_res) { \
return Oxide::Internal::make_unexpected(std::move(_ox_res.error())); \
} \
}
#define OX_TRY(expr) \
__extension__({ \
auto _ox_res = (expr); \
if (!_ox_res) { \
return Oxide::Internal::make_unexpected(std::move(_ox_res.error())); \
} \
std::move(*_ox_res); \
})
#define OX_TRY_DISCARD(expr) \
{ \
auto _ox_res = (expr); \
if (!_ox_res) { \
return Oxide::Internal::make_unexpected(std::move(_ox_res.error())); \
} \
OX_UNUSED(*_ox_res); \
}
```
Note: no need to explicity use `Oxide::` prefix as Oxide namespace is almost always globally used in IA projects.
All variables (local, member and parameter/argument) MUST always be wrapped in one of `Const<T>, Mut<T>, Ref<T>, MutRef<T>` or `ForwardRef<T>`.
> For outer most template of parameters/arguments, use the following Rule to decide between `Ref<T>` or `Const<T>`:
> 1) Is the parameter size <= 64, then use `Const`
> 2) Otherwise use `Ref`
| Use This | Instead of This |
| :---- | :---- |
| ```Box``` | ```std::unique_ptr``` |
| ```Arc``` | ```std::shared_ptr``` |
| ```Weak``` | ```std::weak_ptr``` |
| ```make_box``` | ```std::make_unique``` |
| ```make_arc``` | ```std::make_shared``` |
---
### **2. Naming Conventions**
We use **Rust Naming Conventions** to strictly distinguish Types from Values.
| Element | Style | Example |
| :---- | :---- | :---- |
| **Types / Classes** | PascalCase | ```StreamReader, TcpSocket``` |
| **Functions** | snake_case | ```read_bytes(), create_instance()``` |
| **Variables** | snake_case | ```buffer_size, socket_id``` |
| **Private Members** | m_snake_case | ```m_parser, m_data_size``` |
| **Constants** | SCREAMING_SNAKE | ```MAX_PATH_LENGTH``` |
| **Namespaces** | PascalCase | ```IACore, Oxide, IACore::Env``` |
| **Files** | PascalCase | ```StreamReader.hpp``` |
**Rule:** Never use Hungarian notation (e.g., iCount, strName) except for the m_ prefix on private members.
---
### **3. Primitives Types**
Do not use standard C++ primitives (int, long, unsigned int, double, char).
Use the IACore Rust Aliases defined in IACore.hpp.
| Use This | Instead of This |
| :---- | :---- |
| ```i8, i16, i32, i64``` | ```int8_t, short, int, long long``` |
| ```u8, u16, u32, u64``` | ```uint8_t, unsigned short, unsigned int``` |
| ```f32, f64``` | ```float, double``` |
| ```usize``` | ```size_t, std::size_t``` |
| ```isize``` | ```std::ptrdiff_t``` |
**Exception:** Use char only for C-string literals or std::format compatibility.
---
### **4. Ownership & Pointers**
Adhere to strict ownership semantics. **Raw pointers (T\*) are non-owning.**
* **Box (ia::Box<T>):** Exclusive ownership. Use ia::make_box<T>().
* **Arc (ia::Arc<T>):** Shared ownership (atomic ref-counting). Use sparingly.
* **Raw Pointers (T\*):** Borrowed, non-owning, mutable view. **Must not be deleted.**
* **Const Pointers (const T\*):** Borrowed, non-owning, read-only view.
**Forbidden:**
* new / delete / malloc / free.
* Passing std::shared_ptr by value (unless sharing ownership is the intent).
---
### **5. Error Handling**
Exceptions are BANNED.
All fallible functions must return ia::Result<T>.
**Correct:**
```cpp
// Returns value OR error string
auto read_file(const Path& path) -> ia::Result<String>;
```
Checking Errors (The IA_TRY Macro):
Use IA_TRY to propagate errors (equivalent to Rust's ? operator).
```cpp
auto process_data() -> Result<String> {
IA_TRY(auto data, read_file("test.txt")); // Returns error if read_file fails
return process(data);
}
```
---
### **6. Function Signatures**
Use **Trailing Return Syntax** for all functions (even void returns). This aligns with Rust (fn name() -> type) and handles complex template returns better.
**Correct:**
```cpp
auto calculate_sum(u32 a, u32 b) -> u32;
auto do_something() -> void;
```
**Incorrect:**
```cpp
u32 calculate_sum(u32 a, u32 b);
void do_something();
```
---
### **7. Const Correctness and Auto Usage**
Immutable by Default.
`auto` keyword is BANNED.
Variables should be const unless mutation is explicitly required.
**Correct:**
```cpp
Const<String> path = "data.bin";
Const<i32> result = process(path);
```
**Incorrect:**
```cpp
String path = "data.bin";
const auto result = process(path);
```
---
### **8. Macros**
Avoid Macros.
Use constexpr for constants and inline templates for logic.
* **Allowed:** IA_TRY, IA_NODISCARD, Platform detection (internal).
* **Banned:** TRUE, FALSE, CONST, IN, OUT.
### **9. Class Design (The "Safe Wrapper" Pattern)**
If a class wraps a C-library or raw resource (like simdjson), it must:
1. Be **Move-Only** (Delete Copy Constructor).
2. Use a **Factory Method** (create()) that returns Result<Box<T>> or Result<T>.
3. Never expose raw handles that outlive the wrapper.
```cpp
class SafeWrapper {
public:
static auto create() -> Result<SafeWrapper>;
SafeWrapper(SafeWrapper&&) = default;
SafeWrapper(const SafeWrapper&) = delete;
};
```
---