147 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			V
		
	
	
| module main
 | |
| 
 | |
| import os
 | |
| import flag
 | |
| import strings
 | |
| 
 | |
| const (
 | |
| 	tool_version     = '0.0.4'
 | |
| 	tool_description = 'Converts a list of arbitrary files into a single v module file.'
 | |
| )
 | |
| 
 | |
| struct Context {
 | |
| mut:
 | |
| 	files       []string
 | |
| 	prefix      string
 | |
| 	show_help   bool
 | |
| 	module_name string
 | |
| 	write_file  string
 | |
| }
 | |
| 
 | |
| fn (context Context) header() string {
 | |
| 	mut header_s := ''
 | |
| 	header_s += 'module $context.module_name\n'
 | |
| 	header_s += '\n'
 | |
| 	allfiles := context.files.join(' ')
 | |
| 	mut options := []string{}
 | |
| 	if context.prefix.len > 0 {
 | |
| 		options << '-p $context.prefix'
 | |
| 	}
 | |
| 	if context.module_name.len > 0 {
 | |
| 		options << '-m $context.module_name'
 | |
| 	}
 | |
| 	if context.write_file.len > 0 {
 | |
| 		options << '-w $context.write_file'
 | |
| 	}
 | |
| 	soptions := options.join(' ')
 | |
| 	header_s += '// File generated by:\n'
 | |
| 	header_s += '// v bin2v $allfiles $soptions\n'
 | |
| 	header_s += '// Please, do not edit this file.\n'
 | |
| 	header_s += '// Your changes may be overwritten.\n'
 | |
| 	header_s += 'const (\n'
 | |
| 	return header_s
 | |
| }
 | |
| 
 | |
| fn (context Context) footer() string {
 | |
| 	return ')\n'
 | |
| }
 | |
| 
 | |
| fn (context Context) file2v(bname string, fbytes []u8, bn_max int) string {
 | |
| 	mut sb := strings.new_builder(1000)
 | |
| 	bn_diff_len := bn_max - bname.len
 | |
| 	sb.write_string('\t${bname}_len' + ' '.repeat(bn_diff_len - 4) + ' = $fbytes.len\n')
 | |
| 	fbyte := fbytes[0]
 | |
| 	bnmae_line := '\t$bname' + ' '.repeat(bn_diff_len) + ' = [u8($fbyte), '
 | |
| 	sb.write_string(bnmae_line)
 | |
| 	mut line_len := bnmae_line.len + 3
 | |
| 	for i := 1; i < fbytes.len; i++ {
 | |
| 		b := int(fbytes[i]).str()
 | |
| 		if line_len > 94 {
 | |
| 			sb.go_back(1)
 | |
| 			sb.write_string('\n\t\t')
 | |
| 			line_len = 8
 | |
| 		}
 | |
| 		if i == fbytes.len - 1 {
 | |
| 			sb.write_string(b)
 | |
| 			line_len += b.len
 | |
| 		} else {
 | |
| 			sb.write_string('$b, ')
 | |
| 			line_len += b.len + 2
 | |
| 		}
 | |
| 	}
 | |
| 	sb.write_string(']!\n')
 | |
| 	return sb.str()
 | |
| }
 | |
| 
 | |
| fn (context Context) bname_and_bytes(file string) ?(string, []u8) {
 | |
| 	fname := os.file_name(file)
 | |
| 	fname_escaped := fname.replace_each(['.', '_', '-', '_'])
 | |
| 	byte_name := '$context.prefix$fname_escaped'.to_lower()
 | |
| 	fbytes := os.read_bytes(file) or { return error('Error: $err.msg()') }
 | |
| 	return byte_name, fbytes
 | |
| }
 | |
| 
 | |
| fn (context Context) max_bname_len(bnames []string) int {
 | |
| 	mut max := 0
 | |
| 	for n in bnames {
 | |
| 		if n.len > max {
 | |
| 			max = n.len
 | |
| 		}
 | |
| 	}
 | |
| 	// Add 4 to max due to "_len" suffix
 | |
| 	return max + 4
 | |
| }
 | |
| 
 | |
| fn main() {
 | |
| 	mut context := Context{}
 | |
| 	mut fp := flag.new_flag_parser(os.args[1..])
 | |
| 	fp.application('v bin2v')
 | |
| 	fp.version(tool_version)
 | |
| 	fp.description(tool_description)
 | |
| 	fp.arguments_description('FILE [FILE]...')
 | |
| 	context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
 | |
| 	context.module_name = fp.string('module', `m`, 'binary', 'Name of the generated module.')
 | |
| 	context.prefix = fp.string('prefix', `p`, '', 'A prefix put before each resource name.')
 | |
| 	context.write_file = fp.string('write', `w`, '', 'Write directly to a file with the given name.')
 | |
| 	if context.show_help {
 | |
| 		println(fp.usage())
 | |
| 		exit(0)
 | |
| 	}
 | |
| 	files := fp.finalize() or {
 | |
| 		eprintln('Error: $err.msg()')
 | |
| 		exit(1)
 | |
| 	}
 | |
| 	real_files := files.filter(it != 'bin2v')
 | |
| 	if real_files.len == 0 {
 | |
| 		println(fp.usage())
 | |
| 		exit(0)
 | |
| 	}
 | |
| 	context.files = real_files
 | |
| 	if context.write_file != '' && os.file_ext(context.write_file) !in ['.vv', '.v'] {
 | |
| 		context.write_file += '.v'
 | |
| 	}
 | |
| 	mut file_byte_map := map[string][]u8{}
 | |
| 	for file in real_files {
 | |
| 		bname, fbytes := context.bname_and_bytes(file) or {
 | |
| 			eprintln(err.msg())
 | |
| 			exit(1)
 | |
| 		}
 | |
| 		file_byte_map[bname] = fbytes
 | |
| 	}
 | |
| 	max_bname := context.max_bname_len(file_byte_map.keys())
 | |
| 	if context.write_file.len > 0 {
 | |
| 		mut out_file := os.create(context.write_file)?
 | |
| 		out_file.write_string(context.header())?
 | |
| 		for bname, fbytes in file_byte_map {
 | |
| 			out_file.write_string(context.file2v(bname, fbytes, max_bname))?
 | |
| 		}
 | |
| 		out_file.write_string(context.footer())?
 | |
| 	} else {
 | |
| 		print(context.header())
 | |
| 		for bname, fbytes in file_byte_map {
 | |
| 			print(context.file2v(bname, fbytes, max_bname))
 | |
| 		}
 | |
| 		print(context.footer())
 | |
| 	}
 | |
| }
 |