mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
refactor(dynamic): enhance migration harnesses with Prisma, Sequelize-CLI, Laravel, Rails, Flask support; implement fallback logic and extend SQL framework integration
This commit is contained in:
parent
ed8decb510
commit
fd39304eed
7 changed files with 431 additions and 14 deletions
|
|
@ -133,15 +133,25 @@ const NODE_KNEX: &[VersionedPackage] = &[VersionedPackage {
|
|||
name: "knex",
|
||||
version: "^3.1.0",
|
||||
}];
|
||||
const NODE_PRISMA: &[VersionedPackage] = &[VersionedPackage {
|
||||
name: "@prisma/client",
|
||||
version: "^5.14.0",
|
||||
}];
|
||||
const NODE_PRISMA: &[VersionedPackage] = &[
|
||||
VersionedPackage {
|
||||
name: "@prisma/client",
|
||||
version: "^5.14.0",
|
||||
},
|
||||
VersionedPackage {
|
||||
name: "prisma",
|
||||
version: "^5.14.0",
|
||||
},
|
||||
];
|
||||
const NODE_SEQUELIZE: &[VersionedPackage] = &[
|
||||
VersionedPackage {
|
||||
name: "sequelize",
|
||||
version: "^6.37.3",
|
||||
},
|
||||
VersionedPackage {
|
||||
name: "sequelize-cli",
|
||||
version: "^6.6.2",
|
||||
},
|
||||
VersionedPackage {
|
||||
name: "sqlite3",
|
||||
version: "^5.1.7",
|
||||
|
|
|
|||
|
|
@ -1582,6 +1582,11 @@ fn emit_migration(spec: &HarnessSpec, version: Option<&str>, is_typescript: bool
|
|||
let (preamble, entry_subpath) = nyx_js_preamble(spec, is_typescript);
|
||||
let handler = &spec.entry_name;
|
||||
let version_repr = version.unwrap_or("<no-version>");
|
||||
let framework = spec
|
||||
.framework
|
||||
.as_ref()
|
||||
.map(|binding| binding.adapter.as_str())
|
||||
.unwrap_or("");
|
||||
let body = format!(
|
||||
r#"{preamble}
|
||||
// Phase 21 (Track M.3) — migration.
|
||||
|
|
@ -1591,6 +1596,7 @@ if (_h == null) {{
|
|||
process.stderr.write('NYX_HANDLER_NOT_FOUND: ' + {handler:?} + '\n');
|
||||
process.exit(78);
|
||||
}}
|
||||
const _nyxFramework = {framework:?};
|
||||
function _nyxLooksLikeSql(sql) {{
|
||||
const upper = String(sql).toUpperCase();
|
||||
return ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'ALTER', 'DROP'].some((k) => upper.includes(k));
|
||||
|
|
@ -1618,6 +1624,124 @@ function _nyxMigrationSqlRecord(sql, driver) {{
|
|||
const sqliteDriver = _nyxTryExecuteSqlite(sql);
|
||||
__nyx_stub_sql_record(String(sql), {{ driver: driver, source: 'migration', sqlite_driver: sqliteDriver }});
|
||||
}}
|
||||
function _nyxCliBin(names) {{
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const suffix = process.platform === 'win32' ? '.cmd' : '';
|
||||
for (const name of names) {{
|
||||
const candidate = path.join(__dirname, 'node_modules', '.bin', name + suffix);
|
||||
if (fs.existsSync(candidate)) return candidate;
|
||||
}}
|
||||
return null;
|
||||
}}
|
||||
function _nyxWriteSequelizeCliConfig(configPath) {{
|
||||
const open = String.fromCharCode(123);
|
||||
const close = String.fromCharCode(125);
|
||||
const lines = [
|
||||
"const fs = require('fs');",
|
||||
"function record(sql) " + open,
|
||||
" const p = process.env.NYX_SQL_LOG;",
|
||||
" if (!p || !sql) return;",
|
||||
" let out = '# driver: sequelize-cli\\n# source: migration-cli\\n' + String(sql);",
|
||||
" if (!out.endsWith('\\n')) out += '\\n';",
|
||||
" try " + open + " fs.appendFileSync(p, out); " + close + " catch (_) " + open + close,
|
||||
close,
|
||||
"module.exports = " + open + " nyx: " + open + " dialect: 'sqlite', storage: process.env.NYX_SQL_ENDPOINT || 'nyx.sqlite', logging: record " + close + " " + close + ";",
|
||||
];
|
||||
require('fs').writeFileSync(configPath, lines.join('\n'));
|
||||
}}
|
||||
function _nyxTrySequelizeCli() {{
|
||||
if (_nyxFramework !== 'migration-sequelize') return false;
|
||||
try {{
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cp = require('child_process');
|
||||
const bin = _nyxCliBin(['sequelize', 'sequelize-cli']);
|
||||
if (!bin) return false;
|
||||
const migrationsDir = path.join(__dirname, 'migrations');
|
||||
fs.mkdirSync(migrationsDir, {{ recursive: true }});
|
||||
fs.writeFileSync(
|
||||
path.join(migrationsDir, '00000000000000-nyx-migration.js'),
|
||||
"module.exports = require('../" + {entry_subpath:?} + "');\n"
|
||||
);
|
||||
const configPath = path.join(__dirname, 'nyx-sequelize-config.cjs');
|
||||
_nyxWriteSequelizeCliConfig(configPath);
|
||||
const result = cp.spawnSync(bin, [
|
||||
'db:migrate',
|
||||
'--migrations-path', migrationsDir,
|
||||
'--config', configPath,
|
||||
'--env', 'nyx',
|
||||
], {{
|
||||
cwd: __dirname,
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
}});
|
||||
if (result.stdout) process.stdout.write(result.stdout);
|
||||
if (result.stderr) process.stderr.write(result.stderr);
|
||||
return result.status === 0;
|
||||
}} catch (e) {{
|
||||
process.stderr.write('NYX_SEQUELIZE_CLI_FALLBACK: ' + (e && e.message ? e.message : String(e)) + '\n');
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
function _nyxRecordPrismaMigrationFiles(schemaPath) {{
|
||||
try {{
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const root = path.dirname(schemaPath);
|
||||
const migrations = path.join(root, 'migrations');
|
||||
if (!fs.existsSync(migrations)) return;
|
||||
for (const dirent of fs.readdirSync(migrations, {{ withFileTypes: true }})) {{
|
||||
if (!dirent.isDirectory()) continue;
|
||||
const sqlPath = path.join(migrations, dirent.name, 'migration.sql');
|
||||
if (!fs.existsSync(sqlPath)) continue;
|
||||
const sql = fs.readFileSync(sqlPath, 'utf8');
|
||||
_nyxMigrationSqlRecord(sql, 'prisma-cli');
|
||||
}}
|
||||
}} catch (e) {{
|
||||
process.stderr.write('NYX_PRISMA_CLI_SQLLOG_FALLBACK: ' + (e && e.message ? e.message : String(e)) + '\n');
|
||||
}}
|
||||
}}
|
||||
function _nyxTryPrismaCli() {{
|
||||
if (_nyxFramework !== 'migration-prisma') return false;
|
||||
try {{
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cp = require('child_process');
|
||||
const bin = _nyxCliBin(['prisma']);
|
||||
if (!bin) return false;
|
||||
const candidates = [
|
||||
path.join(__dirname, 'prisma', 'schema.prisma'),
|
||||
path.join(__dirname, 'schema.prisma'),
|
||||
];
|
||||
const schemaPath = candidates.find((p) => fs.existsSync(p));
|
||||
if (!schemaPath) return false;
|
||||
if (process.env.NYX_SQL_ENDPOINT && !process.env.DATABASE_URL) {{
|
||||
process.env.DATABASE_URL = 'file:' + process.env.NYX_SQL_ENDPOINT;
|
||||
}}
|
||||
let result = cp.spawnSync(bin, ['migrate', 'deploy', '--schema', schemaPath], {{
|
||||
cwd: __dirname,
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
}});
|
||||
if (result.status !== 0) {{
|
||||
process.stderr.write('NYX_PRISMA_CLI_DEPLOY_FALLBACK: ' + (result.stderr || result.stdout || '') + '\n');
|
||||
result = cp.spawnSync(bin, ['db', 'push', '--skip-generate', '--schema', schemaPath], {{
|
||||
cwd: __dirname,
|
||||
env: process.env,
|
||||
encoding: 'utf8',
|
||||
}});
|
||||
}}
|
||||
if (result.stdout) process.stdout.write(result.stdout);
|
||||
if (result.stderr) process.stderr.write(result.stderr);
|
||||
if (result.status !== 0) return false;
|
||||
_nyxRecordPrismaMigrationFiles(schemaPath);
|
||||
return true;
|
||||
}} catch (e) {{
|
||||
process.stderr.write('NYX_PRISMA_CLI_FALLBACK: ' + (e && e.message ? e.message : String(e)) + '\n');
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
function _nyxTryRealSequelize() {{
|
||||
try {{
|
||||
const SequelizeLib = require('sequelize');
|
||||
|
|
@ -1732,6 +1856,8 @@ async function _nyxTryRealPrismaClient() {{
|
|||
}}
|
||||
(async () => {{
|
||||
try {{
|
||||
if (_nyxTryPrismaCli()) return;
|
||||
if (_nyxTrySequelizeCli()) return;
|
||||
_realPrisma = await _nyxTryRealPrismaClient();
|
||||
if (_realPrisma && _realPrisma.prisma) {{
|
||||
_prisma = _realPrisma.prisma;
|
||||
|
|
@ -1769,6 +1895,8 @@ async function _nyxTryRealPrismaClient() {{
|
|||
preamble = preamble,
|
||||
handler = handler,
|
||||
version = version_repr,
|
||||
framework = framework,
|
||||
entry_subpath = entry_subpath,
|
||||
);
|
||||
HarnessSource {
|
||||
source: body,
|
||||
|
|
@ -3105,7 +3233,7 @@ fn message_handler_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)>
|
|||
}
|
||||
|
||||
fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
||||
if spec.expected_cap != crate::labels::Cap::CODE_EXEC {
|
||||
if !should_stage_framework_dependency_files(spec) {
|
||||
return Vec::new();
|
||||
}
|
||||
let Some(adapter) = spec.framework.as_ref().map(|b| b.adapter.as_str()) else {
|
||||
|
|
@ -3134,6 +3262,14 @@ fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
|||
]
|
||||
}
|
||||
|
||||
fn should_stage_framework_dependency_files(spec: &HarnessSpec) -> bool {
|
||||
spec.expected_cap == crate::labels::Cap::CODE_EXEC
|
||||
|| matches!(
|
||||
&spec.entry_kind,
|
||||
crate::evidence::EntryKind::Migration { .. }
|
||||
)
|
||||
}
|
||||
|
||||
fn js_message_handler_deps(source: &str) -> Vec<(&'static str, &'static str)> {
|
||||
let mut deps = Vec::new();
|
||||
for raw_line in source.lines() {
|
||||
|
|
|
|||
|
|
@ -3135,7 +3135,28 @@ function __nyx_make_middleware_request(string $payload) {{
|
|||
$req = __nyx_make_middleware_request($payload);
|
||||
$next = function ($r) {{ return $r; }};
|
||||
|
||||
function __nyx_try_laravel_pipeline(string $handler, $req, callable $next): bool {{
|
||||
if (!class_exists('Illuminate\\Pipeline\\Pipeline')) return false;
|
||||
try {{
|
||||
$container = class_exists('Illuminate\\Container\\Container')
|
||||
? new Illuminate\Container\Container()
|
||||
: null;
|
||||
$pipeline = $container === null
|
||||
? new Illuminate\Pipeline\Pipeline()
|
||||
: new Illuminate\Pipeline\Pipeline($container);
|
||||
$result = $pipeline->send($req)->through([$handler])->then($next);
|
||||
if ($result !== null) echo (string)$result . "\n";
|
||||
return true;
|
||||
}} catch (Throwable $e) {{
|
||||
fwrite(STDERR, 'NYX_LARAVEL_PIPELINE_FALLBACK: ' . get_class($e) . ': ' . $e->getMessage() . "\n");
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
|
||||
if (class_exists({handler:?})) {{
|
||||
if (__nyx_try_laravel_pipeline({handler:?}, $req, $next)) {{
|
||||
exit(0);
|
||||
}}
|
||||
$inst = new {handler}();
|
||||
if (method_exists($inst, 'handle')) {{
|
||||
try {{
|
||||
|
|
@ -3217,7 +3238,88 @@ function __nyx_try_execute_migration_sqlite($value): string {{
|
|||
}}
|
||||
}}
|
||||
|
||||
function __nyx_snake_migration_name(string $class): string {{
|
||||
$base = preg_replace('/[^A-Za-z0-9]+/', '_', $class);
|
||||
$snake = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $base));
|
||||
return trim($snake, '_') ?: 'nyx_migration';
|
||||
}}
|
||||
|
||||
function __nyx_boot_laravel_database(): bool {{
|
||||
if (!class_exists('Illuminate\\Database\\Capsule\\Manager')) return false;
|
||||
try {{
|
||||
$endpoint = getenv('NYX_SQL_ENDPOINT');
|
||||
if ($endpoint === false || $endpoint === '') $endpoint = ':memory:';
|
||||
$capsule = new Illuminate\Database\Capsule\Manager();
|
||||
$capsule->addConnection([
|
||||
'driver' => 'sqlite',
|
||||
'database' => $endpoint,
|
||||
'prefix' => '',
|
||||
]);
|
||||
$capsule->setAsGlobal();
|
||||
$capsule->bootEloquent();
|
||||
$db = $capsule->getDatabaseManager();
|
||||
$GLOBALS['__nyx_laravel_db'] = $db;
|
||||
if (class_exists('Illuminate\\Container\\Container')) {{
|
||||
$container = new Illuminate\Container\Container();
|
||||
$container->instance('db', $db);
|
||||
$container->instance('db.connection', $db->connection());
|
||||
if (class_exists('Illuminate\\Support\\Facades\\Facade')) {{
|
||||
Illuminate\Support\Facades\Facade::setFacadeApplication($container);
|
||||
}}
|
||||
}}
|
||||
try {{
|
||||
$db->connection()->listen(function ($query) {{
|
||||
$sql = is_object($query) && isset($query->sql) ? $query->sql : (string)$query;
|
||||
__nyx_record_migration_result($sql, 'laravel-listener');
|
||||
}});
|
||||
}} catch (Throwable $e) {{}}
|
||||
return true;
|
||||
}} catch (Throwable $e) {{
|
||||
fwrite(STDERR, 'NYX_LARAVEL_DB_BOOTSTRAP_FALLBACK: ' . get_class($e) . ': ' . $e->getMessage() . "\n");
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
|
||||
function __nyx_try_laravel_migrator(string $class): bool {{
|
||||
if (!class_exists($class)) return false;
|
||||
if (!class_exists('Illuminate\\Database\\Migrations\\Migrator')) return false;
|
||||
if (!class_exists('Illuminate\\Database\\Migrations\\DatabaseMigrationRepository')) return false;
|
||||
if (!class_exists('Illuminate\\Filesystem\\Filesystem')) return false;
|
||||
if (!__nyx_boot_laravel_database()) return false;
|
||||
try {{
|
||||
$db = $GLOBALS['__nyx_laravel_db'] ?? null;
|
||||
if (!$db) return false;
|
||||
}} catch (Throwable $e) {{
|
||||
try {{
|
||||
$db = Illuminate\Support\Facades\DB::getFacadeRoot();
|
||||
}} catch (Throwable $inner) {{
|
||||
fwrite(STDERR, 'NYX_LARAVEL_MIGRATOR_DB_FALLBACK: ' . get_class($inner) . ': ' . $inner->getMessage() . "\n");
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
try {{
|
||||
$repo = new Illuminate\Database\Migrations\DatabaseMigrationRepository($db, 'migrations');
|
||||
if (!$repo->repositoryExists()) {{
|
||||
$repo->createRepository();
|
||||
}}
|
||||
$files = new Illuminate\Filesystem\Filesystem();
|
||||
$migrator = new Illuminate\Database\Migrations\Migrator($repo, $db, $files);
|
||||
$dir = __DIR__ . '/nyx_laravel_migrations';
|
||||
if (!is_dir($dir)) mkdir($dir, 0777, true);
|
||||
$file = $dir . '/2026_01_01_000000_' . __nyx_snake_migration_name($class) . '.php';
|
||||
file_put_contents($file, "<?php\nrequire_once __DIR__ . '/../entry.php';\n");
|
||||
$migrator->run([$dir], ['pretend' => false]);
|
||||
return true;
|
||||
}} catch (Throwable $e) {{
|
||||
fwrite(STDERR, 'NYX_LARAVEL_MIGRATOR_FALLBACK: ' . get_class($e) . ': ' . $e->getMessage() . "\n");
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
|
||||
if (class_exists({handler:?})) {{
|
||||
if (__nyx_try_laravel_migrator({handler:?})) {{
|
||||
exit(0);
|
||||
}}
|
||||
$inst = new {handler}();
|
||||
if (method_exists($inst, 'up')) {{
|
||||
try {{
|
||||
|
|
@ -3258,7 +3360,7 @@ if (class_exists({handler:?})) {{
|
|||
}
|
||||
|
||||
fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
||||
if spec.expected_cap != crate::labels::Cap::CODE_EXEC {
|
||||
if !should_stage_framework_dependency_files(spec) {
|
||||
return Vec::new();
|
||||
}
|
||||
let Some(adapter) = spec.framework.as_ref().map(|b| b.adapter.as_str()) else {
|
||||
|
|
@ -3281,6 +3383,14 @@ fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
|||
vec![("composer.json".to_owned(), body)]
|
||||
}
|
||||
|
||||
fn should_stage_framework_dependency_files(spec: &HarnessSpec) -> bool {
|
||||
spec.expected_cap == crate::labels::Cap::CODE_EXEC
|
||||
|| matches!(
|
||||
&spec.entry_kind,
|
||||
crate::evidence::EntryKind::Migration { .. }
|
||||
)
|
||||
}
|
||||
|
||||
fn build_call_expr(spec: &HarnessSpec, shape: PhpShape, func: &str) -> String {
|
||||
match shape {
|
||||
PhpShape::TopLevelScript => "null".to_owned(),
|
||||
|
|
|
|||
|
|
@ -4026,7 +4026,7 @@ fn message_handler_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)>
|
|||
}
|
||||
|
||||
fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
||||
if spec.expected_cap != crate::labels::Cap::CODE_EXEC {
|
||||
if !should_stage_framework_dependency_files(spec) {
|
||||
return Vec::new();
|
||||
}
|
||||
let Some(adapter) = spec.framework.as_ref().map(|b| b.adapter.as_str()) else {
|
||||
|
|
@ -4049,6 +4049,14 @@ fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
|||
vec![("requirements.txt".to_owned(), body)]
|
||||
}
|
||||
|
||||
fn should_stage_framework_dependency_files(spec: &HarnessSpec) -> bool {
|
||||
spec.expected_cap == crate::labels::Cap::CODE_EXEC
|
||||
|| matches!(
|
||||
&spec.entry_kind,
|
||||
crate::evidence::EntryKind::Migration { .. }
|
||||
)
|
||||
}
|
||||
|
||||
fn python_message_handler_deps(source: &str) -> Vec<&'static str> {
|
||||
let mut deps = Vec::new();
|
||||
for raw_line in source.lines() {
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,51 @@ def __nyx_patch_active_record_sql_recording
|
|||
end
|
||||
end
|
||||
|
||||
def __nyx_try_rails_migration_context(cls, version)
|
||||
return false unless defined?(Rails)
|
||||
return false unless defined?(ActiveRecord::MigrationContext)
|
||||
return false unless Rails.respond_to?(:application) && Rails.application
|
||||
begin
|
||||
paths = []
|
||||
begin
|
||||
app_paths = Rails.application.paths if Rails.application.respond_to?(:paths)
|
||||
if app_paths && app_paths['db/migrate']
|
||||
paths = Array(app_paths['db/migrate'].respond_to?(:existent) ? app_paths['db/migrate'].existent : app_paths['db/migrate'])
|
||||
end
|
||||
rescue StandardError
|
||||
paths = []
|
||||
end
|
||||
paths = [File.dirname(File.expand_path(__FILE__))] if paths.empty?
|
||||
__nyx_patch_active_record_sql_recording
|
||||
context = begin
|
||||
if defined?(ActiveRecord::SchemaMigration)
|
||||
ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration)
|
||||
else
|
||||
ActiveRecord::MigrationContext.new(paths)
|
||||
end
|
||||
end
|
||||
target = nil
|
||||
if version && version != '<no-version>'
|
||||
begin
|
||||
target = Integer(version)
|
||||
rescue ArgumentError
|
||||
target = nil
|
||||
end
|
||||
end
|
||||
if target && target > 0 && context.respond_to?(:run)
|
||||
context.run(:up, target)
|
||||
elsif context.respond_to?(:up)
|
||||
context.up
|
||||
else
|
||||
return false
|
||||
end
|
||||
true
|
||||
rescue StandardError => e
|
||||
STDERR.puts("NYX_RAILS_MIGRATION_CONTEXT_FALLBACK: #{{e.class.name}}: #{{e.message}}")
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# ActiveRecord migrations expose `up` / `down` / `change` on a subclass.
|
||||
if Object.const_defined?({handler:?})
|
||||
cls = Object.const_get({handler:?})
|
||||
|
|
@ -1061,6 +1106,9 @@ if Object.const_defined?({handler:?})
|
|||
if defined?(ActiveRecord::Migration) && cls.is_a?(Class) && cls < ActiveRecord::Migration
|
||||
begin
|
||||
__nyx_patch_active_record_sql_recording
|
||||
if __nyx_try_rails_migration_context(cls, {ver:?})
|
||||
exit 0
|
||||
end
|
||||
cls.migrate(:up)
|
||||
exit 0
|
||||
rescue StandardError => e
|
||||
|
|
@ -1125,7 +1173,7 @@ end
|
|||
}
|
||||
|
||||
fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
||||
if spec.expected_cap != crate::labels::Cap::CODE_EXEC {
|
||||
if !should_stage_framework_dependency_files(spec) {
|
||||
return Vec::new();
|
||||
}
|
||||
let Some(adapter) = spec.framework.as_ref().map(|b| b.adapter.as_str()) else {
|
||||
|
|
@ -1147,6 +1195,14 @@ fn framework_dependency_files(spec: &HarnessSpec) -> Vec<(String, String)> {
|
|||
vec![("Gemfile".to_owned(), body)]
|
||||
}
|
||||
|
||||
fn should_stage_framework_dependency_files(spec: &HarnessSpec) -> bool {
|
||||
spec.expected_cap == crate::labels::Cap::CODE_EXEC
|
||||
|| matches!(
|
||||
&spec.entry_kind,
|
||||
crate::evidence::EntryKind::Migration { .. }
|
||||
)
|
||||
}
|
||||
|
||||
/// Phase 03 — Track J.1 deserialize harness for Ruby.
|
||||
///
|
||||
/// Wraps a call to `Marshal.load(input)` with a const-lookup
|
||||
|
|
|
|||
|
|
@ -698,14 +698,14 @@ fn kafka_parse_produce_request(version: i16, body: &[u8]) -> Vec<(String, i32, S
|
|||
return Vec::new();
|
||||
};
|
||||
let mut out = Vec::new();
|
||||
for _ in 0..topic_len.max(0).min(256) {
|
||||
for _ in 0..topic_len.clamp(0, 256) {
|
||||
let Some(topic) = reader.string() else {
|
||||
break;
|
||||
};
|
||||
let Some(partition_len) = reader.array_len() else {
|
||||
break;
|
||||
};
|
||||
for _ in 0..partition_len.max(0).min(256) {
|
||||
for _ in 0..partition_len.clamp(0, 256) {
|
||||
let Some(partition) = reader.i32() else {
|
||||
break;
|
||||
};
|
||||
|
|
@ -783,7 +783,7 @@ fn kafka_parse_fetch_request(version: i16, body: &[u8]) -> BTreeMap<String, Vec<
|
|||
let Some(topic_len) = reader.array_len() else {
|
||||
return out;
|
||||
};
|
||||
for _ in 0..topic_len.max(0).min(256) {
|
||||
for _ in 0..topic_len.clamp(0, 256) {
|
||||
let Some(topic) = reader.string() else {
|
||||
break;
|
||||
};
|
||||
|
|
@ -791,7 +791,7 @@ fn kafka_parse_fetch_request(version: i16, body: &[u8]) -> BTreeMap<String, Vec<
|
|||
break;
|
||||
};
|
||||
let mut partitions = Vec::new();
|
||||
for _ in 0..partition_len.max(0).min(256) {
|
||||
for _ in 0..partition_len.clamp(0, 256) {
|
||||
let Some(partition) = reader.i32() else {
|
||||
break;
|
||||
};
|
||||
|
|
@ -840,7 +840,7 @@ fn kafka_parse_list_offsets_request(body: &[u8]) -> BTreeMap<String, Vec<(i32, i
|
|||
let Some(topic_len) = reader.array_len() else {
|
||||
return out;
|
||||
};
|
||||
for _ in 0..topic_len.max(0).min(256) {
|
||||
for _ in 0..topic_len.clamp(0, 256) {
|
||||
let Some(topic) = reader.string() else {
|
||||
break;
|
||||
};
|
||||
|
|
@ -848,7 +848,7 @@ fn kafka_parse_list_offsets_request(body: &[u8]) -> BTreeMap<String, Vec<(i32, i
|
|||
break;
|
||||
};
|
||||
let mut partitions = Vec::new();
|
||||
for _ in 0..partition_len.max(0).min(256) {
|
||||
for _ in 0..partition_len.clamp(0, 256) {
|
||||
let Some(partition) = reader.i32() else {
|
||||
break;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue