diff --git a/compiled_starters/cpp/src/Server.cpp b/compiled_starters/cpp/src/Server.cpp index 099a4c73..0fce76b9 100644 --- a/compiled_starters/cpp/src/Server.cpp +++ b/compiled_starters/cpp/src/Server.cpp @@ -12,50 +12,49 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; // You can use print statements as follows for debugging, they'll be visible when running tests. std::cout << "Logs from your program will appear here!\n"; // Uncomment this block to pass the first stage - // - // int server_fd = socket(AF_INET, SOCK_STREAM, 0); - // if (server_fd < 0) { - // std::cerr << "Failed to create server socket\n"; - // return 1; - // } - // - // // Since the tester restarts your program quite often, setting SO_REUSEADDR - // // ensures that we don't run into 'Address already in use' errors - // int reuse = 1; - // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - // std::cerr << "setsockopt failed\n"; - // return 1; - // } - // - // struct sockaddr_in server_addr; - // server_addr.sin_family = AF_INET; - // server_addr.sin_addr.s_addr = INADDR_ANY; - // server_addr.sin_port = htons(6379); - // - // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - // std::cerr << "Failed to bind to port 6379\n"; - // return 1; - // } - // - // int connection_backlog = 5; - // if (listen(server_fd, connection_backlog) != 0) { - // std::cerr << "listen failed\n"; - // return 1; - // } - // - // struct sockaddr_in client_addr; - // int client_addr_len = sizeof(client_addr); - // - // std::cout << "Waiting for a client to connect...\n"; - // + // // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); // std::cout << "Client connected\n"; - // + // // close(server_fd); return 0; diff --git a/solutions/cpp/01-jm1/code/src/Server.cpp b/solutions/cpp/01-jm1/code/src/Server.cpp index 336f97d5..73dc9398 100644 --- a/solutions/cpp/01-jm1/code/src/Server.cpp +++ b/solutions/cpp/01-jm1/code/src/Server.cpp @@ -12,13 +12,13 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; - + int server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { std::cerr << "Failed to create server socket\n"; return 1; } - + // Since the tester restarts your program quite often, setting SO_REUSEADDR // ensures that we don't run into 'Address already in use' errors int reuse = 1; @@ -26,26 +26,25 @@ int main(int argc, char **argv) { std::cerr << "setsockopt failed\n"; return 1; } - + struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(6379); - + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { std::cerr << "Failed to bind to port 6379\n"; return 1; } - + int connection_backlog = 5; if (listen(server_fd, connection_backlog) != 0) { std::cerr << "listen failed\n"; return 1; } - + struct sockaddr_in client_addr; int client_addr_len = sizeof(client_addr); - std::cout << "Waiting for a client to connect...\n"; accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); diff --git a/solutions/cpp/01-jm1/diff/src/Server.cpp.diff b/solutions/cpp/01-jm1/diff/src/Server.cpp.diff index 2236b95d..bb71a1b3 100644 --- a/solutions/cpp/01-jm1/diff/src/Server.cpp.diff +++ b/solutions/cpp/01-jm1/diff/src/Server.cpp.diff @@ -1,100 +1,40 @@ -@@ -1,62 +1,57 @@ - #include - #include - #include - #include - #include - #include - #include - #include - #include - - int main(int argc, char **argv) { - // Flush after every std::cout / std::cerr - std::cout << std::unitbuf; - std::cerr << std::unitbuf; +@@ -25,37 +25,32 @@ + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; - // You can use print statements as follows for debugging, they'll be visible when running tests. - std::cout << "Logs from your program will appear here!\n"; -+ int server_fd = socket(AF_INET, SOCK_STREAM, 0); -+ if (server_fd < 0) { -+ std::cerr << "Failed to create server socket\n"; -+ return 1; -+ } ++ accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); ++ std::cout << "Client connected\n"; - // Uncomment this block to pass the first stage -- // -- // int server_fd = socket(AF_INET, SOCK_STREAM, 0); -- // if (server_fd < 0) { -- // std::cerr << "Failed to create server socket\n"; -- // return 1; -- // } -- // -- // // Since the tester restarts your program quite often, setting SO_REUSEADDR -- // // ensures that we don't run into 'Address already in use' errors -- // int reuse = 1; -- // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { -- // std::cerr << "setsockopt failed\n"; -- // return 1; -- // } -- // -- // struct sockaddr_in server_addr; -- // server_addr.sin_family = AF_INET; -- // server_addr.sin_addr.s_addr = INADDR_ANY; -- // server_addr.sin_port = htons(6379); -- // -- // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { -- // std::cerr << "Failed to bind to port 6379\n"; -- // return 1; -- // } -- // -- // int connection_backlog = 5; -- // if (listen(server_fd, connection_backlog) != 0) { -- // std::cerr << "listen failed\n"; -- // return 1; -- // } -- // -- // struct sockaddr_in client_addr; -- // int client_addr_len = sizeof(client_addr); -- // -- // std::cout << "Waiting for a client to connect...\n"; -- // +- // - // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); - // std::cout << "Client connected\n"; -- // +- // - // close(server_fd); -+ // Since the tester restarts your program quite often, setting SO_REUSEADDR -+ // ensures that we don't run into 'Address already in use' errors -+ int reuse = 1; -+ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { -+ std::cerr << "setsockopt failed\n"; -+ return 1; -+ } -+ -+ struct sockaddr_in server_addr; -+ server_addr.sin_family = AF_INET; -+ server_addr.sin_addr.s_addr = INADDR_ANY; -+ server_addr.sin_port = htons(6379); -+ -+ if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { -+ std::cerr << "Failed to bind to port 6379\n"; -+ return 1; -+ } -+ -+ int connection_backlog = 5; -+ if (listen(server_fd, connection_backlog) != 0) { -+ std::cerr << "listen failed\n"; -+ return 1; -+ } -+ -+ struct sockaddr_in client_addr; -+ int client_addr_len = sizeof(client_addr); -+ -+ std::cout << "Waiting for a client to connect...\n"; -+ -+ accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); -+ std::cout << "Client connected\n"; -+ + close(server_fd); return 0; diff --git a/solutions/cpp/01-jm1/explanation.md b/solutions/cpp/01-jm1/explanation.md index 08233f4a..0072b775 100644 --- a/solutions/cpp/01-jm1/explanation.md +++ b/solutions/cpp/01-jm1/explanation.md @@ -5,41 +5,6 @@ Study and uncomment the relevant code: ```cpp // Uncomment this block to pass the first stage -int server_fd = socket(AF_INET, SOCK_STREAM, 0); -if (server_fd < 0) { - std::cerr << "Failed to create server socket\n"; - return 1; -} - -// Since the tester restarts your program quite often, setting SO_REUSEADDR -// ensures that we don't run into 'Address already in use' errors -int reuse = 1; -if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - std::cerr << "setsockopt failed\n"; - return 1; -} - -struct sockaddr_in server_addr; -server_addr.sin_family = AF_INET; -server_addr.sin_addr.s_addr = INADDR_ANY; -server_addr.sin_port = htons(6379); - -if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - std::cerr << "Failed to bind to port 6379\n"; - return 1; -} - -int connection_backlog = 5; -if (listen(server_fd, connection_backlog) != 0) { - std::cerr << "listen failed\n"; - return 1; -} - -struct sockaddr_in client_addr; -int client_addr_len = sizeof(client_addr); - -std::cout << "Waiting for a client to connect...\n"; - accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); std::cout << "Client connected\n"; diff --git a/solutions/cpp/02-rg2/code/.codecrafters/compile.sh b/solutions/cpp/02-rg2/code/.codecrafters/compile.sh new file mode 100755 index 00000000..9da226b3 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.codecrafters/compile.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake +cmake --build ./build diff --git a/solutions/cpp/02-rg2/code/.codecrafters/run.sh b/solutions/cpp/02-rg2/code/.codecrafters/run.sh new file mode 100755 index 00000000..afe22862 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec ./build/server "$@" diff --git a/solutions/cpp/02-rg2/code/.gitattributes b/solutions/cpp/02-rg2/code/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/solutions/cpp/02-rg2/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/cpp/02-rg2/code/.gitignore b/solutions/cpp/02-rg2/code/.gitignore new file mode 100644 index 00000000..d66be1c6 --- /dev/null +++ b/solutions/cpp/02-rg2/code/.gitignore @@ -0,0 +1,49 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +server + +# CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +build/ +vcpkg_installed \ No newline at end of file diff --git a/solutions/cpp/02-rg2/code/CMakeLists.txt b/solutions/cpp/02-rg2/code/CMakeLists.txt new file mode 100644 index 00000000..4993f2ba --- /dev/null +++ b/solutions/cpp/02-rg2/code/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) + +project(redis-starter-cpp) + +file(GLOB_RECURSE SOURCE_FILES src/*.cpp) + +set(CMAKE_CXX_STANDARD 23) # Enable the C++23 standard +set(THREADS_PREFER_PTHREAD_FLAG ON) + +find_package(Threads REQUIRED) +find_package(asio CONFIG REQUIRED) + +add_executable(server ${SOURCE_FILES}) + +target_link_libraries(server PRIVATE asio asio::asio) +target_link_libraries(server PRIVATE Threads::Threads) \ No newline at end of file diff --git a/solutions/cpp/02-rg2/code/README.md b/solutions/cpp/02-rg2/code/README.md new file mode 100644 index 00000000..fb2bc917 --- /dev/null +++ b/solutions/cpp/02-rg2/code/README.md @@ -0,0 +1,33 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/redis.png) + +This is a starting point for C++ solutions to the +["Build Your Own Redis" Challenge](https://codecrafters.io/challenges/redis). + +In this challenge, you'll build a toy Redis clone that's capable of handling +basic commands like `PING`, `SET` and `GET`. Along the way we'll learn about +event loops, the Redis protocol and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Redis implementation is in `src/Server.cpp`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `cmake` installed locally +1. Run `./your_program.sh` to run your Redis server, which is implemented in + `src/Server.cpp`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. diff --git a/solutions/cpp/02-rg2/code/codecrafters.yml b/solutions/cpp/02-rg2/code/codecrafters.yml new file mode 100644 index 00000000..ad26fa0d --- /dev/null +++ b/solutions/cpp/02-rg2/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the C++ version used to run your code +# on Codecrafters. +# +# Available versions: cpp-23 +language_pack: cpp-23 diff --git a/solutions/cpp/02-rg2/code/src/Server.cpp b/solutions/cpp/02-rg2/code/src/Server.cpp new file mode 100644 index 00000000..30c7f5f2 --- /dev/null +++ b/solutions/cpp/02-rg2/code/src/Server.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + // Flush after every std::cout / std::cerr + std::cout << std::unitbuf; + std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; + + int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); + std::cout << "Client connected\n"; + + std::string response = "+PONG\r\n"; + send(client_fd, response.c_str(), response.size(), 0); + + close(client_fd); + close(server_fd); + + return 0; +} diff --git a/solutions/cpp/02-rg2/code/vcpkg-configuration.json b/solutions/cpp/02-rg2/code/vcpkg-configuration.json new file mode 100644 index 00000000..16b40d6b --- /dev/null +++ b/solutions/cpp/02-rg2/code/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "c4af3593e1f1aa9e14a560a09e45ea2cb0dfd74d", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", + "name": "microsoft" + } + ] +} diff --git a/solutions/cpp/02-rg2/code/vcpkg.json b/solutions/cpp/02-rg2/code/vcpkg.json new file mode 100644 index 00000000..c4ec5d26 --- /dev/null +++ b/solutions/cpp/02-rg2/code/vcpkg.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "asio", + "pthreads" + ] +} diff --git a/solutions/cpp/02-rg2/code/your_program.sh b/solutions/cpp/02-rg2/code/your_program.sh new file mode 100755 index 00000000..c493a3e7 --- /dev/null +++ b/solutions/cpp/02-rg2/code/your_program.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake + cmake --build ./build +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec ./build/server "$@" diff --git a/solutions/cpp/02-rg2/diff/src/Server.cpp.diff b/solutions/cpp/02-rg2/diff/src/Server.cpp.diff new file mode 100644 index 00000000..01bdd258 --- /dev/null +++ b/solutions/cpp/02-rg2/diff/src/Server.cpp.diff @@ -0,0 +1,38 @@ +@@ -25,32 +25,36 @@ + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; + +- accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); ++ int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); + std::cout << "Client connected\n"; + ++ std::string response = "+PONG\r\n"; ++ send(client_fd, response.c_str(), response.size(), 0); ++ ++ close(client_fd); + close(server_fd); + + return 0; + } diff --git a/solutions/cpp/02-rg2/explanation.md b/solutions/cpp/02-rg2/explanation.md new file mode 100644 index 00000000..08233f4a --- /dev/null +++ b/solutions/cpp/02-rg2/explanation.md @@ -0,0 +1,55 @@ +The entry point for your Redis implementation is in `src/Server.cpp`. + +Study and uncomment the relevant code: + +```cpp +// Uncomment this block to pass the first stage + +int server_fd = socket(AF_INET, SOCK_STREAM, 0); +if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; +} + +// Since the tester restarts your program quite often, setting SO_REUSEADDR +// ensures that we don't run into 'Address already in use' errors +int reuse = 1; +if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; +} + +struct sockaddr_in server_addr; +server_addr.sin_family = AF_INET; +server_addr.sin_addr.s_addr = INADDR_ANY; +server_addr.sin_port = htons(6379); + +if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; +} + +int connection_backlog = 5; +if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; +} + +struct sockaddr_in client_addr; +int client_addr_len = sizeof(client_addr); + +std::cout << "Waiting for a client to connect...\n"; + +accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); +std::cout << "Client connected\n"; + +close(server_fd); +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/solutions/go/02-rg2/code/.codecrafters/compile.sh b/solutions/go/02-rg2/code/.codecrafters/compile.sh new file mode 100755 index 00000000..99120b97 --- /dev/null +++ b/solutions/go/02-rg2/code/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +go build -o /tmp/codecrafters-build-redis-go app/*.go diff --git a/solutions/go/02-rg2/code/.codecrafters/run.sh b/solutions/go/02-rg2/code/.codecrafters/run.sh new file mode 100755 index 00000000..c67e187c --- /dev/null +++ b/solutions/go/02-rg2/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec /tmp/codecrafters-build-redis-go "$@" diff --git a/solutions/go/02-rg2/code/.gitattributes b/solutions/go/02-rg2/code/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/solutions/go/02-rg2/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/go/02-rg2/code/README.md b/solutions/go/02-rg2/code/README.md new file mode 100644 index 00000000..c808b2b0 --- /dev/null +++ b/solutions/go/02-rg2/code/README.md @@ -0,0 +1,33 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/redis.png) + +This is a starting point for Go solutions to the +["Build Your Own Redis" Challenge](https://codecrafters.io/challenges/redis). + +In this challenge, you'll build a toy Redis clone that's capable of handling +basic commands like `PING`, `SET` and `GET`. Along the way we'll learn about +event loops, the Redis protocol and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Redis implementation is in `app/server.go`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `go (1.19)` installed locally +1. Run `./your_program.sh` to run your Redis server, which is implemented in + `app/server.go`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. diff --git a/solutions/go/02-rg2/code/app/server.go b/solutions/go/02-rg2/code/app/server.go new file mode 100644 index 00000000..0012443c --- /dev/null +++ b/solutions/go/02-rg2/code/app/server.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "net" + "os" +) + +// Ensures gofmt doesn't remove the "net" and "os" imports in stage 1 (feel free to remove this!) +var _ = net.Listen +var _ = os.Exit + +func main() { + l, err := net.Listen("tcp", "0.0.0.0:6379") + if err != nil { + fmt.Println("Failed to bind to port 6379") + os.Exit(1) + } + conn, err := l.Accept() + if err != nil { + fmt.Println("Error accepting connection: ", err.Error()) + os.Exit(1) + } + conn.Write([]byte("+PONG\r\n")) +} diff --git a/solutions/go/02-rg2/code/codecrafters.yml b/solutions/go/02-rg2/code/codecrafters.yml new file mode 100644 index 00000000..77886cfb --- /dev/null +++ b/solutions/go/02-rg2/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Go version used to run your code +# on Codecrafters. +# +# Available versions: go-1.22 +language_pack: go-1.22 diff --git a/solutions/go/02-rg2/code/go.mod b/solutions/go/02-rg2/code/go.mod new file mode 100644 index 00000000..a8e2d2af --- /dev/null +++ b/solutions/go/02-rg2/code/go.mod @@ -0,0 +1,11 @@ +// DON'T EDIT THIS! +// +// Codecrafters relies on this file being intact to run tests successfully. Any changes +// here will not reflect when CodeCrafters tests your code, and might even cause build +// failures. +// +// DON'T EDIT THIS! + +module github.com/codecrafters-io/redis-starter-go + +go 1.22 diff --git a/solutions/go/02-rg2/code/go.sum b/solutions/go/02-rg2/code/go.sum new file mode 100644 index 00000000..e69de29b diff --git a/solutions/go/02-rg2/code/your_program.sh b/solutions/go/02-rg2/code/your_program.sh new file mode 100755 index 00000000..8b5fdeb7 --- /dev/null +++ b/solutions/go/02-rg2/code/your_program.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + go build -o /tmp/codecrafters-build-redis-go app/*.go +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec /tmp/codecrafters-build-redis-go "$@" diff --git a/solutions/go/02-rg2/diff/app/server.go.diff b/solutions/go/02-rg2/diff/app/server.go.diff new file mode 100644 index 00000000..6deba0be --- /dev/null +++ b/solutions/go/02-rg2/diff/app/server.go.diff @@ -0,0 +1,27 @@ +@@ -1,24 +1,25 @@ + package main + + import ( + "fmt" + "net" + "os" + ) + + // Ensures gofmt doesn't remove the "net" and "os" imports in stage 1 (feel free to remove this!) + var _ = net.Listen + var _ = os.Exit + + func main() { + l, err := net.Listen("tcp", "0.0.0.0:6379") + if err != nil { + fmt.Println("Failed to bind to port 6379") + os.Exit(1) + } +- _, err = l.Accept() ++ conn, err := l.Accept() + if err != nil { + fmt.Println("Error accepting connection: ", err.Error()) + os.Exit(1) + } ++ conn.Write([]byte("+PONG\r\n")) + } diff --git a/solutions/go/02-rg2/explanation.md b/solutions/go/02-rg2/explanation.md new file mode 100644 index 00000000..d1e9f947 --- /dev/null +++ b/solutions/go/02-rg2/explanation.md @@ -0,0 +1,26 @@ +The entry point for your Redis implementation is in `app/server.go`. + +Study and uncomment the relevant code: + +```go +// Uncomment this block to pass the first stage + +l, err := net.Listen("tcp", "0.0.0.0:6379") +if err != nil { + fmt.Println("Failed to bind to port 6379") + os.Exit(1) +} +_, err = l.Accept() +if err != nil { + fmt.Println("Error accepting connection: ", err.Error()) + os.Exit(1) +} +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/solutions/java/02-rg2/code/.codecrafters/compile.sh b/solutions/java/02-rg2/code/.codecrafters/compile.sh new file mode 100755 index 00000000..4380e12a --- /dev/null +++ b/solutions/java/02-rg2/code/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +mvn -B package -Ddir=/tmp/codecrafters-build-redis-java diff --git a/solutions/java/02-rg2/code/.codecrafters/run.sh b/solutions/java/02-rg2/code/.codecrafters/run.sh new file mode 100755 index 00000000..c7683250 --- /dev/null +++ b/solutions/java/02-rg2/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec java -jar /tmp/codecrafters-build-redis-java/codecrafters-redis.jar "$@" diff --git a/solutions/java/02-rg2/code/.gitattributes b/solutions/java/02-rg2/code/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/solutions/java/02-rg2/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/java/02-rg2/code/.gitignore b/solutions/java/02-rg2/code/.gitignore new file mode 100644 index 00000000..a48b18a1 --- /dev/null +++ b/solutions/java/02-rg2/code/.gitignore @@ -0,0 +1,3 @@ +*.jar +target/ +.idea/ diff --git a/solutions/java/02-rg2/code/README.md b/solutions/java/02-rg2/code/README.md new file mode 100644 index 00000000..9aa3c645 --- /dev/null +++ b/solutions/java/02-rg2/code/README.md @@ -0,0 +1,34 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/redis.png) + +This is a starting point for Java solutions to the +["Build Your Own Redis" Challenge](https://codecrafters.io/challenges/redis). + +In this challenge, you'll build a toy Redis clone that's capable of handling +basic commands like `PING`, `SET` and `GET`. Along the way we'll learn about +event loops, the Redis protocol and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Redis implementation is in `src/main/java/Main.java`. +Study and uncomment the relevant code, and push your changes to pass the first +stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `mvn` installed locally +1. Run `./your_program.sh` to run your Redis server, which is implemented in + `src/main/java/Main.java`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. diff --git a/solutions/java/02-rg2/code/codecrafters.yml b/solutions/java/02-rg2/code/codecrafters.yml new file mode 100644 index 00000000..2406954b --- /dev/null +++ b/solutions/java/02-rg2/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Java version used to run your code +# on Codecrafters. +# +# Available versions: java-23 +language_pack: java-23 diff --git a/solutions/java/02-rg2/code/pom.xml b/solutions/java/02-rg2/code/pom.xml new file mode 100644 index 00000000..1b269b22 --- /dev/null +++ b/solutions/java/02-rg2/code/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + io.codecrafters + codecrafters-redis + 1.0 + + + 23 + 23 + UTF-8 + 23 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + codecrafters-redis + + jar-with-dependencies + + false + + + true + + Main + + + ${dir} + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/solutions/java/02-rg2/code/src/main/java/Main.java b/solutions/java/02-rg2/code/src/main/java/Main.java new file mode 100644 index 00000000..f4a8c33d --- /dev/null +++ b/solutions/java/02-rg2/code/src/main/java/Main.java @@ -0,0 +1,32 @@ +import java.io.IOException; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; + +public class Main { + public static void main(String[] args){ + ServerSocket serverSocket = null; + Socket clientSocket = null; + int port = 6379; + try { + serverSocket = new ServerSocket(port); + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + serverSocket.setReuseAddress(true); + // Wait for connection from client. + clientSocket = serverSocket.accept(); + OutputStream outputStream = clientSocket.getOutputStream(); + outputStream.write("+PONG\r\n".getBytes()); + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } finally { + try { + if (clientSocket != null) { + clientSocket.close(); + } + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } + } + } +} diff --git a/solutions/java/02-rg2/code/your_program.sh b/solutions/java/02-rg2/code/your_program.sh new file mode 100755 index 00000000..c6f54bcd --- /dev/null +++ b/solutions/java/02-rg2/code/your_program.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + mvn -B package -Ddir=/tmp/codecrafters-build-redis-java +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec java -jar /tmp/codecrafters-build-redis-java/codecrafters-redis.jar "$@" diff --git a/solutions/java/02-rg2/diff/src/main/java/Main.java.diff b/solutions/java/02-rg2/diff/src/main/java/Main.java.diff new file mode 100644 index 00000000..78e2e087 --- /dev/null +++ b/solutions/java/02-rg2/diff/src/main/java/Main.java.diff @@ -0,0 +1,33 @@ +@@ -1,29 +1,32 @@ + import java.io.IOException; ++import java.io.OutputStream; + import java.net.ServerSocket; + import java.net.Socket; + + public class Main { + public static void main(String[] args){ + ServerSocket serverSocket = null; + Socket clientSocket = null; + int port = 6379; + try { + serverSocket = new ServerSocket(port); + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + serverSocket.setReuseAddress(true); + // Wait for connection from client. + clientSocket = serverSocket.accept(); ++ OutputStream outputStream = clientSocket.getOutputStream(); ++ outputStream.write("+PONG\r\n".getBytes()); + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } finally { + try { + if (clientSocket != null) { + clientSocket.close(); + } + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } + } + } + } diff --git a/solutions/java/02-rg2/explanation.md b/solutions/java/02-rg2/explanation.md new file mode 100644 index 00000000..43cdf65d --- /dev/null +++ b/solutions/java/02-rg2/explanation.md @@ -0,0 +1,36 @@ +The entry point for your Redis implementation is in `src/main/java/Main.java`. + +Study and uncomment the relevant code: + +```java +// Uncomment this block to pass the first stage + ServerSocket serverSocket = null; + Socket clientSocket = null; + int port = 6379; + try { + serverSocket = new ServerSocket(port); + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + serverSocket.setReuseAddress(true); + // Wait for connection from client. + clientSocket = serverSocket.accept(); + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } finally { + try { + if (clientSocket != null) { + clientSocket.close(); + } + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } + } +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/solutions/rust/02-rg2/code/.codecrafters/compile.sh b/solutions/rust/02-rg2/code/.codecrafters/compile.sh new file mode 100755 index 00000000..22e2eba8 --- /dev/null +++ b/solutions/rust/02-rg2/code/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +cargo build --release --target-dir=/tmp/codecrafters-redis-target --manifest-path Cargo.toml diff --git a/solutions/rust/02-rg2/code/.codecrafters/run.sh b/solutions/rust/02-rg2/code/.codecrafters/run.sh new file mode 100755 index 00000000..ac9e5ca7 --- /dev/null +++ b/solutions/rust/02-rg2/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec /tmp/codecrafters-redis-target/release/redis-starter-rust "$@" \ No newline at end of file diff --git a/solutions/rust/02-rg2/code/.gitattributes b/solutions/rust/02-rg2/code/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/solutions/rust/02-rg2/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/rust/02-rg2/code/.gitignore b/solutions/rust/02-rg2/code/.gitignore new file mode 100644 index 00000000..73fab072 --- /dev/null +++ b/solutions/rust/02-rg2/code/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/solutions/rust/02-rg2/code/Cargo.lock b/solutions/rust/02-rg2/code/Cargo.lock new file mode 100644 index 00000000..7146a975 --- /dev/null +++ b/solutions/rust/02-rg2/code/Cargo.lock @@ -0,0 +1,457 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5208975e568d83b6b05cc0a063c8e7e9acc2b43bee6da15616a5b73e109d7437" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +dependencies = [ + "memchr", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redis-starter-rust" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "thiserror", + "tokio", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/solutions/rust/02-rg2/code/Cargo.toml b/solutions/rust/02-rg2/code/Cargo.toml new file mode 100644 index 00000000..157cbb7f --- /dev/null +++ b/solutions/rust/02-rg2/code/Cargo.toml @@ -0,0 +1,25 @@ +# DON'T EDIT THIS! +# +# Codecrafters relies on this file being intact to run tests successfully. Any changes +# here will not reflect when CodeCrafters tests your code, and might even cause build +# failures. +# +# DON'T EDIT THIS! +[package] +name = "redis-starter-rust" +version = "0.1.0" +authors = ["Codecrafters "] +edition = "2021" + +# DON'T EDIT THIS! +# +# Codecrafters relies on this file being intact to run tests successfully. Any changes +# here will not reflect when CodeCrafters tests your code, and might even cause build +# failures. +# +# DON'T EDIT THIS! +[dependencies] +anyhow = "1.0.59" # error handling +bytes = "1.3.0" # helps manage buffers +thiserror = "1.0.32" # error handling +tokio = { version = "1.23.0", features = ["full"] } # async networking diff --git a/solutions/rust/02-rg2/code/README.md b/solutions/rust/02-rg2/code/README.md new file mode 100644 index 00000000..b1857224 --- /dev/null +++ b/solutions/rust/02-rg2/code/README.md @@ -0,0 +1,34 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/redis.png) + +This is a starting point for Rust solutions to the +["Build Your Own Redis" Challenge](https://codecrafters.io/challenges/redis). + +In this challenge, you'll build a toy Redis clone that's capable of handling +basic commands like `PING`, `SET` and `GET`. Along the way we'll learn about +event loops, the Redis protocol and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Redis implementation is in `src/main.rs`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `cargo (1.82)` installed locally +1. Run `./your_program.sh` to run your Redis server, which is implemented in + `src/main.rs`. This command compiles your Rust project, so it might be slow + the first time you run it. Subsequent runs will be fast. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. diff --git a/solutions/rust/02-rg2/code/codecrafters.yml b/solutions/rust/02-rg2/code/codecrafters.yml new file mode 100644 index 00000000..fe3fb234 --- /dev/null +++ b/solutions/rust/02-rg2/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Rust version used to run your code +# on Codecrafters. +# +# Available versions: rust-1.82 +language_pack: rust-1.82 diff --git a/solutions/rust/02-rg2/code/src/main.rs b/solutions/rust/02-rg2/code/src/main.rs new file mode 100644 index 00000000..7887b6ce --- /dev/null +++ b/solutions/rust/02-rg2/code/src/main.rs @@ -0,0 +1,18 @@ +#![allow(unused_imports)] +use std::io::Write; +use std::net::TcpListener; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:6379").unwrap(); + + for stream in listener.incoming() { + match stream { + Ok(mut stream) => { + stream.write_all(b"+PONG\r\n").unwrap(); + } + Err(e) => { + println!("error: {}", e); + } + } + } +} diff --git a/solutions/rust/02-rg2/code/your_program.sh b/solutions/rust/02-rg2/code/your_program.sh new file mode 100755 index 00000000..8f4b2dde --- /dev/null +++ b/solutions/rust/02-rg2/code/your_program.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + cargo build --release --target-dir=/tmp/codecrafters-redis-target --manifest-path Cargo.toml +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec /tmp/codecrafters-redis-target/release/redis-starter-rust "$@" diff --git a/solutions/rust/02-rg2/diff/src/main.rs.diff b/solutions/rust/02-rg2/diff/src/main.rs.diff new file mode 100644 index 00000000..4ee01163 --- /dev/null +++ b/solutions/rust/02-rg2/diff/src/main.rs.diff @@ -0,0 +1,21 @@ +@@ -1,17 +1,18 @@ + #![allow(unused_imports)] ++use std::io::Write; + use std::net::TcpListener; + + fn main() { + let listener = TcpListener::bind("127.0.0.1:6379").unwrap(); + + for stream in listener.incoming() { + match stream { +- Ok(_stream) => { +- println!("accepted new connection"); ++ Ok(mut stream) => { ++ stream.write_all(b"+PONG\r\n").unwrap(); + } + Err(e) => { + println!("error: {}", e); + } + } + } + } diff --git a/solutions/rust/02-rg2/explanation.md b/solutions/rust/02-rg2/explanation.md new file mode 100644 index 00000000..a930dcc1 --- /dev/null +++ b/solutions/rust/02-rg2/explanation.md @@ -0,0 +1,28 @@ +The entry point for your Redis implementation is in `src/main.rs`. + +Study and uncomment the relevant code: + +```rust +// Uncomment this block to pass the first stage + +let listener = TcpListener::bind("127.0.0.1:6379").unwrap(); + +for stream in listener.incoming() { + match stream { + Ok(_stream) => { + println!("accepted new connection"); + } + Err(e) => { + println!("error: {}", e); + } + } +} +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/starter_templates/cpp/code/src/Server.cpp b/starter_templates/cpp/code/src/Server.cpp index 099a4c73..0fce76b9 100644 --- a/starter_templates/cpp/code/src/Server.cpp +++ b/starter_templates/cpp/code/src/Server.cpp @@ -12,50 +12,49 @@ int main(int argc, char **argv) { // Flush after every std::cout / std::cerr std::cout << std::unitbuf; std::cerr << std::unitbuf; + + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + std::cerr << "Failed to create server socket\n"; + return 1; + } + + // Since the tester restarts your program quite often, setting SO_REUSEADDR + // ensures that we don't run into 'Address already in use' errors + int reuse = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { + std::cerr << "setsockopt failed\n"; + return 1; + } + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6379); + + if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { + std::cerr << "Failed to bind to port 6379\n"; + return 1; + } + + int connection_backlog = 5; + if (listen(server_fd, connection_backlog) != 0) { + std::cerr << "listen failed\n"; + return 1; + } + + struct sockaddr_in client_addr; + int client_addr_len = sizeof(client_addr); + std::cout << "Waiting for a client to connect...\n"; // You can use print statements as follows for debugging, they'll be visible when running tests. std::cout << "Logs from your program will appear here!\n"; // Uncomment this block to pass the first stage - // - // int server_fd = socket(AF_INET, SOCK_STREAM, 0); - // if (server_fd < 0) { - // std::cerr << "Failed to create server socket\n"; - // return 1; - // } - // - // // Since the tester restarts your program quite often, setting SO_REUSEADDR - // // ensures that we don't run into 'Address already in use' errors - // int reuse = 1; - // if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { - // std::cerr << "setsockopt failed\n"; - // return 1; - // } - // - // struct sockaddr_in server_addr; - // server_addr.sin_family = AF_INET; - // server_addr.sin_addr.s_addr = INADDR_ANY; - // server_addr.sin_port = htons(6379); - // - // if (bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) != 0) { - // std::cerr << "Failed to bind to port 6379\n"; - // return 1; - // } - // - // int connection_backlog = 5; - // if (listen(server_fd, connection_backlog) != 0) { - // std::cerr << "listen failed\n"; - // return 1; - // } - // - // struct sockaddr_in client_addr; - // int client_addr_len = sizeof(client_addr); - // - // std::cout << "Waiting for a client to connect...\n"; - // + // // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len); // std::cout << "Client connected\n"; - // + // // close(server_fd); return 0;